| Yes | | The style of the drawer container. |
155 | | drawerName | string | No | | The name of the drawer component.
156 | | direction | string | Yes | left | The direction to open the drawer, one of: ["left", "right"].
157 | | passProps | object | Yes | | The values passed to the drawer. See props in RNNDrawer above.
158 | | options | Options | Yes | | The options to configure properties of the React Native Navigation native screen. Refer to React Native Navigation's options object.
159 | | swipeSensitivity | number | Yes | 0.2 | The sensitivity of the swipe to invoke each function. |
160 | | sideMargin | number | Yes | 15 | The size of the gutter for both sides. |
161 | | sideMarginLeft | number | Yes | | The size of the gutter for the left side. |
162 | | sideMarginRight | number | Yes | | The size of the gutter for the right side. |
163 |
164 | ## Contributors ✨
165 |
166 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
167 |
168 |
169 |
170 |
171 |
179 |
180 |
181 |
182 |
183 |
184 |
185 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
186 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] };
2 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 |
33 | # node.js
34 | #
35 | node_modules/
36 | npm-debug.log
37 | yarn-error.log
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | */fastlane/report.xml
52 | */fastlane/Preview.html
53 | */fastlane/screenshots
54 |
55 | # Bundle artifact
56 | *.jsbundle
57 |
58 | # CocoaPods
59 | ios/Pods
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Example Project
2 |
3 | 
4 |
5 | This project contains a complete example of the `react-native-navigation-drawer-extension` package.
6 |
7 | The entry point is at `index.js`, replacing the default RN content with the listener from `react-native-navigation` to start the app.
8 |
9 | The pages and components are in the `src` folder.
10 |
11 |
--------------------------------------------------------------------------------
/example/__tests__/App-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import 'react-native';
6 | import React from 'react';
7 | import App from '../App';
8 |
9 | // Note: test renderer must be required after react-native.
10 | import renderer from 'react-test-renderer';
11 |
12 | it('renders correctly', () => {
13 | renderer.create( );
14 | });
15 |
--------------------------------------------------------------------------------
/example/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.awesomeproject",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.awesomeproject",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation. If none specified and
19 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is
20 | * // default. Can be overridden with ENTRY_FILE environment variable.
21 | * entryFile: "index.android.js",
22 | *
23 | * // https://reactnative.dev/docs/performance#enable-the-ram-format
24 | * bundleCommand: "ram-bundle",
25 | *
26 | * // whether to bundle JS and assets in debug mode
27 | * bundleInDebug: false,
28 | *
29 | * // whether to bundle JS and assets in release mode
30 | * bundleInRelease: true,
31 | *
32 | * // whether to bundle JS and assets in another build variant (if configured).
33 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
34 | * // The configuration property can be in the following formats
35 | * // 'bundleIn${productFlavor}${buildType}'
36 | * // 'bundleIn${buildType}'
37 | * // bundleInFreeDebug: true,
38 | * // bundleInPaidRelease: true,
39 | * // bundleInBeta: true,
40 | *
41 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
42 | * // for example: to disable dev mode in the staging build type (if configured)
43 | * devDisabledInStaging: true,
44 | * // The configuration property can be in the following formats
45 | * // 'devDisabledIn${productFlavor}${buildType}'
46 | * // 'devDisabledIn${buildType}'
47 | *
48 | * // the root of your project, i.e. where "package.json" lives
49 | * root: "../../",
50 | *
51 | * // where to put the JS bundle asset in debug mode
52 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
53 | *
54 | * // where to put the JS bundle asset in release mode
55 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
56 | *
57 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
58 | * // require('./image.png')), in debug mode
59 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
60 | *
61 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
62 | * // require('./image.png')), in release mode
63 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
64 | *
65 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
66 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
67 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
68 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
69 | * // for example, you might want to remove it from here.
70 | * inputExcludes: ["android/**", "ios/**"],
71 | *
72 | * // override which node gets called and with what additional arguments
73 | * nodeExecutableAndArgs: ["node"],
74 | *
75 | * // supply additional arguments to the packager
76 | * extraPackagerArgs: []
77 | * ]
78 | */
79 |
80 | project.ext.react = [
81 | enableHermes: false, // clean and rebuild if changing
82 | ]
83 |
84 | apply from: "../../node_modules/react-native/react.gradle"
85 |
86 | /**
87 | * Set this to true to create two separate APKs instead of one:
88 | * - An APK that only works on ARM devices
89 | * - An APK that only works on x86 devices
90 | * The advantage is the size of the APK is reduced by about 4MB.
91 | * Upload all the APKs to the Play Store and people will download
92 | * the correct one based on the CPU architecture of their device.
93 | */
94 | def enableSeparateBuildPerCPUArchitecture = false
95 |
96 | /**
97 | * Run Proguard to shrink the Java bytecode in release builds.
98 | */
99 | def enableProguardInReleaseBuilds = false
100 |
101 | /**
102 | * The preferred build flavor of JavaScriptCore.
103 | *
104 | * For example, to use the international variant, you can use:
105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
106 | *
107 | * The international variant includes ICU i18n library and necessary data
108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
109 | * give correct results when using with locales other than en-US. Note that
110 | * this variant is about 6MiB larger per architecture than default.
111 | */
112 | def jscFlavor = 'org.webkit:android-jsc:+'
113 |
114 | /**
115 | * Whether to enable the Hermes VM.
116 | *
117 | * This should be set on project.ext.react and mirrored here. If it is not set
118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
119 | * and the benefits of using Hermes will therefore be sharply reduced.
120 | */
121 | def enableHermes = project.ext.react.get("enableHermes", false);
122 |
123 | android {
124 | compileSdkVersion rootProject.ext.compileSdkVersion
125 |
126 | compileOptions {
127 | sourceCompatibility JavaVersion.VERSION_1_8
128 | targetCompatibility JavaVersion.VERSION_1_8
129 | }
130 |
131 | defaultConfig {
132 | applicationId "com.awesomeproject"
133 | minSdkVersion rootProject.ext.minSdkVersion
134 | targetSdkVersion rootProject.ext.targetSdkVersion
135 | versionCode 1
136 | versionName "1.0"
137 | multiDexEnabled true
138 | }
139 | splits {
140 | abi {
141 | reset()
142 | enable enableSeparateBuildPerCPUArchitecture
143 | universalApk false // If true, also generate a universal APK
144 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
145 | }
146 | }
147 | signingConfigs {
148 | debug {
149 | storeFile file('debug.keystore')
150 | storePassword 'android'
151 | keyAlias 'androiddebugkey'
152 | keyPassword 'android'
153 | }
154 | }
155 | buildTypes {
156 | debug {
157 | signingConfig signingConfigs.debug
158 | }
159 | release {
160 | // Caution! In production, you need to generate your own keystore file.
161 | // see https://reactnative.dev/docs/signed-apk-android.
162 | signingConfig signingConfigs.debug
163 | minifyEnabled enableProguardInReleaseBuilds
164 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
165 | }
166 | }
167 |
168 | // applicationVariants are e.g. debug, release
169 | applicationVariants.all { variant ->
170 | variant.outputs.each { output ->
171 | // For each separate APK per architecture, set a unique version code as described here:
172 | // https://developer.android.com/studio/build/configure-apk-splits.html
173 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
174 | def abi = output.getFilter(OutputFile.ABI)
175 | if (abi != null) { // null for the universal-debug, universal-release variants
176 | output.versionCodeOverride =
177 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
178 | }
179 |
180 | }
181 | }
182 | }
183 |
184 | dependencies {
185 | implementation fileTree(dir: "libs", include: ["*.jar"])
186 | //noinspection GradleDynamicVersion
187 | implementation "com.facebook.react:react-native:+" // From node_modules
188 |
189 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
190 |
191 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
192 | exclude group:'com.facebook.fbjni'
193 | }
194 |
195 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
196 | exclude group:'com.facebook.flipper'
197 | exclude group:'com.squareup.okhttp3', module:'okhttp'
198 | }
199 |
200 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
201 | exclude group:'com.facebook.flipper'
202 | }
203 |
204 | if (enableHermes) {
205 | def hermesPath = "../../node_modules/hermes-engine/android/";
206 | debugImplementation files(hermesPath + "hermes-debug.aar")
207 | releaseImplementation files(hermesPath + "hermes-release.aar")
208 | } else {
209 | implementation jscFlavor
210 | }
211 | }
212 |
213 | // Run this once to be able to run the application with BUCK
214 | // puts all compile dependencies into folder libs for BUCK to use
215 | task copyDownloadableDepsToLibs(type: Copy) {
216 | from configurations.compile
217 | into 'libs'
218 | }
219 |
220 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
221 |
--------------------------------------------------------------------------------
/example/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/awesomeproject/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.awesomeproject;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceManager;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.modules.network.NetworkingModule;
25 | import okhttp3.OkHttpClient;
26 |
27 | public class ReactNativeFlipper {
28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
29 | if (FlipperUtils.shouldEnableFlipper(context)) {
30 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
31 |
32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
33 | client.addPlugin(new ReactFlipperPlugin());
34 | client.addPlugin(new DatabasesFlipperPlugin(context));
35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
36 | client.addPlugin(CrashReporterPlugin.getInstance());
37 |
38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39 | NetworkingModule.setCustomClientBuilder(
40 | new NetworkingModule.CustomClientBuilder() {
41 | @Override
42 | public void apply(OkHttpClient.Builder builder) {
43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44 | }
45 | });
46 | client.addPlugin(networkFlipperPlugin);
47 | client.start();
48 |
49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
50 | // Hence we run if after all native modules have been initialized
51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
52 | if (reactContext == null) {
53 | reactInstanceManager.addReactInstanceEventListener(
54 | new ReactInstanceManager.ReactInstanceEventListener() {
55 | @Override
56 | public void onReactContextInitialized(ReactContext reactContext) {
57 | reactInstanceManager.removeReactInstanceEventListener(this);
58 | reactContext.runOnNativeModulesQueueThread(
59 | new Runnable() {
60 | @Override
61 | public void run() {
62 | client.addPlugin(new FrescoFlipperPlugin());
63 | }
64 | });
65 | }
66 | });
67 | } else {
68 | client.addPlugin(new FrescoFlipperPlugin());
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/awesomeproject/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.awesomeproject;
2 |
3 | import com.reactnativenavigation.NavigationActivity;
4 |
5 | public class MainActivity extends NavigationActivity {
6 |
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/awesomeproject/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.awesomeproject;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.reactnativenavigation.NavigationApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.reactnativenavigation.react.NavigationReactNativeHost;
10 | import com.facebook.react.ReactPackage;
11 | import com.facebook.soloader.SoLoader;
12 | import java.lang.reflect.InvocationTargetException;
13 | import java.util.List;
14 |
15 | public class MainApplication extends NavigationApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost =
18 | new NavigationReactNativeHost(this) {
19 | @Override
20 | public boolean getUseDeveloperSupport() {
21 | return BuildConfig.DEBUG;
22 | }
23 |
24 | @Override
25 | protected List getPackages() {
26 | @SuppressWarnings("UnnecessaryLocalVariable")
27 | List packages = new PackageList(this).getPackages();
28 | // Packages that cannot be autolinked yet can be added manually here, for example:
29 | // packages.add(new MyReactNativePackage());
30 | return packages;
31 | }
32 |
33 | @Override
34 | protected String getJSMainModuleName() {
35 | return "index";
36 | }
37 | };
38 |
39 | @Override
40 | public ReactNativeHost getReactNativeHost() {
41 | return mReactNativeHost;
42 | }
43 |
44 | @Override
45 | public void onCreate() {
46 | super.onCreate();
47 |
48 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
49 | }
50 |
51 | /**
52 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
53 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
54 | *
55 | * @param context
56 | * @param reactInstanceManager
57 | */
58 | private static void initializeFlipper(
59 | Context context, ReactInstanceManager reactInstanceManager) {
60 | if (BuildConfig.DEBUG) {
61 | try {
62 | /*
63 | We use reflection here to pick up the class that initializes Flipper,
64 | since Flipper library is not available in release mode
65 | */
66 | Class> aClass = Class.forName("com.awesomeproject.ReactNativeFlipper");
67 | aClass
68 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
69 | .invoke(null, context, reactInstanceManager);
70 | } catch (ClassNotFoundException e) {
71 | e.printStackTrace();
72 | } catch (NoSuchMethodException e) {
73 | e.printStackTrace();
74 | } catch (IllegalAccessException e) {
75 | e.printStackTrace();
76 | } catch (InvocationTargetException e) {
77 | e.printStackTrace();
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AwesomeProject
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | RNNKotlinVersion = "1.3.61"
6 | buildToolsVersion = "29.0.2"
7 | minSdkVersion = 19
8 | compileSdkVersion = 29
9 | targetSdkVersion = 29
10 | }
11 | repositories {
12 | google()
13 | jcenter()
14 | }
15 | dependencies {
16 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
17 | classpath("com.android.tools.build:gradle:3.5.3")
18 | // NOTE: Do not place your application dependencies here; they belong
19 | // in the individual module build.gradle files
20 | }
21 | }
22 |
23 | allprojects {
24 | repositories {
25 | mavenLocal()
26 | maven {
27 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
28 | url("$rootDir/../node_modules/react-native/android")
29 | }
30 | maven {
31 | // Android JSC is installed from npm
32 | url("$rootDir/../node_modules/jsc-android/dist")
33 | }
34 |
35 | google()
36 | jcenter()
37 | maven { url 'https://www.jitpack.io' }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.54.0
29 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lukebrandonfarrell/react-native-navigation-drawer-extension/f705aca041a652aa45daf08c631bc197e11f0f41/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin or MSYS, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=`expr $i + 1`
158 | done
159 | case $i in
160 | 0) set -- ;;
161 | 1) set -- "$args0" ;;
162 | 2) set -- "$args0" "$args1" ;;
163 | 3) set -- "$args0" "$args1" "$args2" ;;
164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=`save "$@"`
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | exec "$JAVACMD" "$@"
184 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 | @rem Execute Gradle
88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
89 |
90 | :end
91 | @rem End local scope for the variables with windows NT shell
92 | if "%ERRORLEVEL%"=="0" goto mainEnd
93 |
94 | :fail
95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
96 | rem the _cmd.exe /c_ return code!
97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
98 | exit /b 1
99 |
100 | :mainEnd
101 | if "%OS%"=="Windows_NT" endlocal
102 |
103 | :omega
104 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'AwesomeProject'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "AwesomeProject",
3 | "displayName": "AwesomeProject"
4 | }
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import {Navigation} from 'react-native-navigation';
2 | import {RNNDrawer} from 'react-native-navigation-drawer-extension';
3 |
4 | import CustomDrawer from './src/components/CustomDrawer';
5 | import AnotherPage from './src/pages/AnotherPage';
6 | import HomePage from './src/pages/HomePage';
7 | import Page1 from './src/pages/Page1';
8 | import Page2 from './src/pages/Page2';
9 |
10 | Navigation.registerComponent('HomePage', () => HomePage);
11 | Navigation.registerComponent('CustomDrawer', () =>
12 | RNNDrawer.create(CustomDrawer),
13 | );
14 | Navigation.registerComponent('AnotherPage', () => AnotherPage);
15 | Navigation.registerComponent('Page1', () => Page1);
16 | Navigation.registerComponent('Page2', () => Page2);
17 |
18 | Navigation.events().registerAppLaunchedListener(() => {
19 | Navigation.setRoot({
20 | root: {
21 | stack: {
22 | children: [
23 | {
24 | component: {
25 | name: 'HomePage',
26 | },
27 | },
28 | ],
29 | },
30 | },
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSExceptionDomains
28 |
29 | localhost
30 |
31 | NSExceptionAllowsInsecureHTTPLoads
32 |
33 |
34 |
35 |
36 | NSLocationWhenInUseUsageDescription
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject-tvOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : UIResponder
5 |
6 | @property (nonatomic, strong) UIWindow *window;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #ifdef FB_SONARKIT_ENABLED
8 | #import
9 | #import
10 | #import
11 | #import
12 | #import
13 | #import
14 |
15 | static void InitializeFlipper(UIApplication *application) {
16 | FlipperClient *client = [FlipperClient sharedClient];
17 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
18 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
19 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
20 | [client addPlugin:[FlipperKitReactPlugin new]];
21 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
22 | [client start];
23 | }
24 | #endif
25 |
26 | @implementation AppDelegate
27 |
28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
29 | {
30 | #ifdef FB_SONARKIT_ENABLED
31 | InitializeFlipper(application);
32 | #endif
33 |
34 | [ReactNativeNavigation bootstrapWithDelegate:self launchOptions:launchOptions];
35 | return YES;
36 | }
37 |
38 | - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge {
39 | return [ReactNativeNavigation extraModulesForBridge:bridge];
40 | }
41 |
42 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
43 | {
44 | #if DEBUG
45 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
46 | #else
47 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
48 | #endif
49 | }
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | AwesomeProject
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | NSLocationWhenInUseUsageDescription
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIViewControllerBasedStatusBarAppearance
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProject/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char * argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProjectTests/AwesomeProjectTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface AwesomeProjectTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation AwesomeProjectTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
38 | if (level >= RCTLogLevelError) {
39 | redboxError = message;
40 | }
41 | });
42 | #endif
43 |
44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 |
48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
50 | return YES;
51 | }
52 | return NO;
53 | }];
54 | }
55 |
56 | #ifdef DEBUG
57 | RCTSetLogFunction(RCTDefaultLogFunction);
58 | #endif
59 |
60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
62 | }
63 |
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/example/ios/AwesomeProjectTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | require_relative '../node_modules/react-native/scripts/react_native_pods'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | platform :ios, '11.0'
5 |
6 | target 'AwesomeProject' do
7 | config = use_native_modules!
8 |
9 | use_react_native!(:path => config["reactNativePath"])
10 |
11 | target 'AwesomeProjectTests' do
12 | inherit! :complete
13 | # Pods for testing
14 | end
15 |
16 | # Enables Flipper.
17 | #
18 | # Note that if you have use_frameworks! enabled, Flipper will not work and
19 | # you should disable these next few lines.
20 | use_flipper!
21 | post_install do |installer|
22 | flipper_post_install(installer)
23 | end
24 | end
25 |
26 | target 'AwesomeProject-tvOS' do
27 | # Pods for AwesomeProject-tvOS
28 |
29 | target 'AwesomeProject-tvOSTests' do
30 | inherit! :search_paths
31 | # Pods for testing
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - boost-for-react-native (1.63.0)
3 | - CocoaAsyncSocket (7.6.4)
4 | - CocoaLibEvent (1.0.0)
5 | - DoubleConversion (1.1.6)
6 | - FBLazyVector (0.63.3)
7 | - FBReactNativeSpec (0.63.3):
8 | - Folly (= 2020.01.13.00)
9 | - RCTRequired (= 0.63.3)
10 | - RCTTypeSafety (= 0.63.3)
11 | - React-Core (= 0.63.3)
12 | - React-jsi (= 0.63.3)
13 | - ReactCommon/turbomodule/core (= 0.63.3)
14 | - Flipper (0.54.0):
15 | - Flipper-Folly (~> 2.2)
16 | - Flipper-RSocket (~> 1.1)
17 | - Flipper-DoubleConversion (1.1.7)
18 | - Flipper-Folly (2.3.0):
19 | - boost-for-react-native
20 | - CocoaLibEvent (~> 1.0)
21 | - Flipper-DoubleConversion
22 | - Flipper-Glog
23 | - OpenSSL-Universal (= 1.0.2.20)
24 | - Flipper-Glog (0.3.6)
25 | - Flipper-PeerTalk (0.0.4)
26 | - Flipper-RSocket (1.1.0):
27 | - Flipper-Folly (~> 2.2)
28 | - FlipperKit (0.54.0):
29 | - FlipperKit/Core (= 0.54.0)
30 | - FlipperKit/Core (0.54.0):
31 | - Flipper (~> 0.54.0)
32 | - FlipperKit/CppBridge
33 | - FlipperKit/FBCxxFollyDynamicConvert
34 | - FlipperKit/FBDefines
35 | - FlipperKit/FKPortForwarding
36 | - FlipperKit/CppBridge (0.54.0):
37 | - Flipper (~> 0.54.0)
38 | - FlipperKit/FBCxxFollyDynamicConvert (0.54.0):
39 | - Flipper-Folly (~> 2.2)
40 | - FlipperKit/FBDefines (0.54.0)
41 | - FlipperKit/FKPortForwarding (0.54.0):
42 | - CocoaAsyncSocket (~> 7.6)
43 | - Flipper-PeerTalk (~> 0.0.4)
44 | - FlipperKit/FlipperKitHighlightOverlay (0.54.0)
45 | - FlipperKit/FlipperKitLayoutPlugin (0.54.0):
46 | - FlipperKit/Core
47 | - FlipperKit/FlipperKitHighlightOverlay
48 | - FlipperKit/FlipperKitLayoutTextSearchable
49 | - YogaKit (~> 1.18)
50 | - FlipperKit/FlipperKitLayoutTextSearchable (0.54.0)
51 | - FlipperKit/FlipperKitNetworkPlugin (0.54.0):
52 | - FlipperKit/Core
53 | - FlipperKit/FlipperKitReactPlugin (0.54.0):
54 | - FlipperKit/Core
55 | - FlipperKit/FlipperKitUserDefaultsPlugin (0.54.0):
56 | - FlipperKit/Core
57 | - FlipperKit/SKIOSNetworkPlugin (0.54.0):
58 | - FlipperKit/Core
59 | - FlipperKit/FlipperKitNetworkPlugin
60 | - Folly (2020.01.13.00):
61 | - boost-for-react-native
62 | - DoubleConversion
63 | - Folly/Default (= 2020.01.13.00)
64 | - glog
65 | - Folly/Default (2020.01.13.00):
66 | - boost-for-react-native
67 | - DoubleConversion
68 | - glog
69 | - glog (0.3.5)
70 | - OpenSSL-Universal (1.0.2.20):
71 | - OpenSSL-Universal/Static (= 1.0.2.20)
72 | - OpenSSL-Universal/Static (1.0.2.20)
73 | - RCTRequired (0.63.3)
74 | - RCTTypeSafety (0.63.3):
75 | - FBLazyVector (= 0.63.3)
76 | - Folly (= 2020.01.13.00)
77 | - RCTRequired (= 0.63.3)
78 | - React-Core (= 0.63.3)
79 | - React (0.63.3):
80 | - React-Core (= 0.63.3)
81 | - React-Core/DevSupport (= 0.63.3)
82 | - React-Core/RCTWebSocket (= 0.63.3)
83 | - React-RCTActionSheet (= 0.63.3)
84 | - React-RCTAnimation (= 0.63.3)
85 | - React-RCTBlob (= 0.63.3)
86 | - React-RCTImage (= 0.63.3)
87 | - React-RCTLinking (= 0.63.3)
88 | - React-RCTNetwork (= 0.63.3)
89 | - React-RCTSettings (= 0.63.3)
90 | - React-RCTText (= 0.63.3)
91 | - React-RCTVibration (= 0.63.3)
92 | - React-callinvoker (0.63.3)
93 | - React-Core (0.63.3):
94 | - Folly (= 2020.01.13.00)
95 | - glog
96 | - React-Core/Default (= 0.63.3)
97 | - React-cxxreact (= 0.63.3)
98 | - React-jsi (= 0.63.3)
99 | - React-jsiexecutor (= 0.63.3)
100 | - Yoga
101 | - React-Core/CoreModulesHeaders (0.63.3):
102 | - Folly (= 2020.01.13.00)
103 | - glog
104 | - React-Core/Default
105 | - React-cxxreact (= 0.63.3)
106 | - React-jsi (= 0.63.3)
107 | - React-jsiexecutor (= 0.63.3)
108 | - Yoga
109 | - React-Core/Default (0.63.3):
110 | - Folly (= 2020.01.13.00)
111 | - glog
112 | - React-cxxreact (= 0.63.3)
113 | - React-jsi (= 0.63.3)
114 | - React-jsiexecutor (= 0.63.3)
115 | - Yoga
116 | - React-Core/DevSupport (0.63.3):
117 | - Folly (= 2020.01.13.00)
118 | - glog
119 | - React-Core/Default (= 0.63.3)
120 | - React-Core/RCTWebSocket (= 0.63.3)
121 | - React-cxxreact (= 0.63.3)
122 | - React-jsi (= 0.63.3)
123 | - React-jsiexecutor (= 0.63.3)
124 | - React-jsinspector (= 0.63.3)
125 | - Yoga
126 | - React-Core/RCTActionSheetHeaders (0.63.3):
127 | - Folly (= 2020.01.13.00)
128 | - glog
129 | - React-Core/Default
130 | - React-cxxreact (= 0.63.3)
131 | - React-jsi (= 0.63.3)
132 | - React-jsiexecutor (= 0.63.3)
133 | - Yoga
134 | - React-Core/RCTAnimationHeaders (0.63.3):
135 | - Folly (= 2020.01.13.00)
136 | - glog
137 | - React-Core/Default
138 | - React-cxxreact (= 0.63.3)
139 | - React-jsi (= 0.63.3)
140 | - React-jsiexecutor (= 0.63.3)
141 | - Yoga
142 | - React-Core/RCTBlobHeaders (0.63.3):
143 | - Folly (= 2020.01.13.00)
144 | - glog
145 | - React-Core/Default
146 | - React-cxxreact (= 0.63.3)
147 | - React-jsi (= 0.63.3)
148 | - React-jsiexecutor (= 0.63.3)
149 | - Yoga
150 | - React-Core/RCTImageHeaders (0.63.3):
151 | - Folly (= 2020.01.13.00)
152 | - glog
153 | - React-Core/Default
154 | - React-cxxreact (= 0.63.3)
155 | - React-jsi (= 0.63.3)
156 | - React-jsiexecutor (= 0.63.3)
157 | - Yoga
158 | - React-Core/RCTLinkingHeaders (0.63.3):
159 | - Folly (= 2020.01.13.00)
160 | - glog
161 | - React-Core/Default
162 | - React-cxxreact (= 0.63.3)
163 | - React-jsi (= 0.63.3)
164 | - React-jsiexecutor (= 0.63.3)
165 | - Yoga
166 | - React-Core/RCTNetworkHeaders (0.63.3):
167 | - Folly (= 2020.01.13.00)
168 | - glog
169 | - React-Core/Default
170 | - React-cxxreact (= 0.63.3)
171 | - React-jsi (= 0.63.3)
172 | - React-jsiexecutor (= 0.63.3)
173 | - Yoga
174 | - React-Core/RCTSettingsHeaders (0.63.3):
175 | - Folly (= 2020.01.13.00)
176 | - glog
177 | - React-Core/Default
178 | - React-cxxreact (= 0.63.3)
179 | - React-jsi (= 0.63.3)
180 | - React-jsiexecutor (= 0.63.3)
181 | - Yoga
182 | - React-Core/RCTTextHeaders (0.63.3):
183 | - Folly (= 2020.01.13.00)
184 | - glog
185 | - React-Core/Default
186 | - React-cxxreact (= 0.63.3)
187 | - React-jsi (= 0.63.3)
188 | - React-jsiexecutor (= 0.63.3)
189 | - Yoga
190 | - React-Core/RCTVibrationHeaders (0.63.3):
191 | - Folly (= 2020.01.13.00)
192 | - glog
193 | - React-Core/Default
194 | - React-cxxreact (= 0.63.3)
195 | - React-jsi (= 0.63.3)
196 | - React-jsiexecutor (= 0.63.3)
197 | - Yoga
198 | - React-Core/RCTWebSocket (0.63.3):
199 | - Folly (= 2020.01.13.00)
200 | - glog
201 | - React-Core/Default (= 0.63.3)
202 | - React-cxxreact (= 0.63.3)
203 | - React-jsi (= 0.63.3)
204 | - React-jsiexecutor (= 0.63.3)
205 | - Yoga
206 | - React-CoreModules (0.63.3):
207 | - FBReactNativeSpec (= 0.63.3)
208 | - Folly (= 2020.01.13.00)
209 | - RCTTypeSafety (= 0.63.3)
210 | - React-Core/CoreModulesHeaders (= 0.63.3)
211 | - React-jsi (= 0.63.3)
212 | - React-RCTImage (= 0.63.3)
213 | - ReactCommon/turbomodule/core (= 0.63.3)
214 | - React-cxxreact (0.63.3):
215 | - boost-for-react-native (= 1.63.0)
216 | - DoubleConversion
217 | - Folly (= 2020.01.13.00)
218 | - glog
219 | - React-callinvoker (= 0.63.3)
220 | - React-jsinspector (= 0.63.3)
221 | - React-jsi (0.63.3):
222 | - boost-for-react-native (= 1.63.0)
223 | - DoubleConversion
224 | - Folly (= 2020.01.13.00)
225 | - glog
226 | - React-jsi/Default (= 0.63.3)
227 | - React-jsi/Default (0.63.3):
228 | - boost-for-react-native (= 1.63.0)
229 | - DoubleConversion
230 | - Folly (= 2020.01.13.00)
231 | - glog
232 | - React-jsiexecutor (0.63.3):
233 | - DoubleConversion
234 | - Folly (= 2020.01.13.00)
235 | - glog
236 | - React-cxxreact (= 0.63.3)
237 | - React-jsi (= 0.63.3)
238 | - React-jsinspector (0.63.3)
239 | - React-RCTActionSheet (0.63.3):
240 | - React-Core/RCTActionSheetHeaders (= 0.63.3)
241 | - React-RCTAnimation (0.63.3):
242 | - FBReactNativeSpec (= 0.63.3)
243 | - Folly (= 2020.01.13.00)
244 | - RCTTypeSafety (= 0.63.3)
245 | - React-Core/RCTAnimationHeaders (= 0.63.3)
246 | - React-jsi (= 0.63.3)
247 | - ReactCommon/turbomodule/core (= 0.63.3)
248 | - React-RCTBlob (0.63.3):
249 | - FBReactNativeSpec (= 0.63.3)
250 | - Folly (= 2020.01.13.00)
251 | - React-Core/RCTBlobHeaders (= 0.63.3)
252 | - React-Core/RCTWebSocket (= 0.63.3)
253 | - React-jsi (= 0.63.3)
254 | - React-RCTNetwork (= 0.63.3)
255 | - ReactCommon/turbomodule/core (= 0.63.3)
256 | - React-RCTImage (0.63.3):
257 | - FBReactNativeSpec (= 0.63.3)
258 | - Folly (= 2020.01.13.00)
259 | - RCTTypeSafety (= 0.63.3)
260 | - React-Core/RCTImageHeaders (= 0.63.3)
261 | - React-jsi (= 0.63.3)
262 | - React-RCTNetwork (= 0.63.3)
263 | - ReactCommon/turbomodule/core (= 0.63.3)
264 | - React-RCTLinking (0.63.3):
265 | - FBReactNativeSpec (= 0.63.3)
266 | - React-Core/RCTLinkingHeaders (= 0.63.3)
267 | - React-jsi (= 0.63.3)
268 | - ReactCommon/turbomodule/core (= 0.63.3)
269 | - React-RCTNetwork (0.63.3):
270 | - FBReactNativeSpec (= 0.63.3)
271 | - Folly (= 2020.01.13.00)
272 | - RCTTypeSafety (= 0.63.3)
273 | - React-Core/RCTNetworkHeaders (= 0.63.3)
274 | - React-jsi (= 0.63.3)
275 | - ReactCommon/turbomodule/core (= 0.63.3)
276 | - React-RCTSettings (0.63.3):
277 | - FBReactNativeSpec (= 0.63.3)
278 | - Folly (= 2020.01.13.00)
279 | - RCTTypeSafety (= 0.63.3)
280 | - React-Core/RCTSettingsHeaders (= 0.63.3)
281 | - React-jsi (= 0.63.3)
282 | - ReactCommon/turbomodule/core (= 0.63.3)
283 | - React-RCTText (0.63.3):
284 | - React-Core/RCTTextHeaders (= 0.63.3)
285 | - React-RCTVibration (0.63.3):
286 | - FBReactNativeSpec (= 0.63.3)
287 | - Folly (= 2020.01.13.00)
288 | - React-Core/RCTVibrationHeaders (= 0.63.3)
289 | - React-jsi (= 0.63.3)
290 | - ReactCommon/turbomodule/core (= 0.63.3)
291 | - ReactCommon/turbomodule/core (0.63.3):
292 | - DoubleConversion
293 | - Folly (= 2020.01.13.00)
294 | - glog
295 | - React-callinvoker (= 0.63.3)
296 | - React-Core (= 0.63.3)
297 | - React-cxxreact (= 0.63.3)
298 | - React-jsi (= 0.63.3)
299 | - ReactNativeNavigation (7.3.0):
300 | - React-Core
301 | - React-RCTImage
302 | - React-RCTText
303 | - ReactNativeNavigation/Core (= 7.3.0)
304 | - ReactNativeNavigation/Core (7.3.0):
305 | - React-Core
306 | - React-RCTImage
307 | - React-RCTText
308 | - Yoga (1.14.0)
309 | - YogaKit (1.18.1):
310 | - Yoga (~> 1.14)
311 |
312 | DEPENDENCIES:
313 | - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
314 | - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
315 | - FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
316 | - Flipper (~> 0.54.0)
317 | - Flipper-DoubleConversion (= 1.1.7)
318 | - Flipper-Folly (~> 2.2)
319 | - Flipper-Glog (= 0.3.6)
320 | - Flipper-PeerTalk (~> 0.0.4)
321 | - Flipper-RSocket (~> 1.1)
322 | - FlipperKit (~> 0.54.0)
323 | - FlipperKit/Core (~> 0.54.0)
324 | - FlipperKit/CppBridge (~> 0.54.0)
325 | - FlipperKit/FBCxxFollyDynamicConvert (~> 0.54.0)
326 | - FlipperKit/FBDefines (~> 0.54.0)
327 | - FlipperKit/FKPortForwarding (~> 0.54.0)
328 | - FlipperKit/FlipperKitHighlightOverlay (~> 0.54.0)
329 | - FlipperKit/FlipperKitLayoutPlugin (~> 0.54.0)
330 | - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.54.0)
331 | - FlipperKit/FlipperKitNetworkPlugin (~> 0.54.0)
332 | - FlipperKit/FlipperKitReactPlugin (~> 0.54.0)
333 | - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.54.0)
334 | - FlipperKit/SKIOSNetworkPlugin (~> 0.54.0)
335 | - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
336 | - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
337 | - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
338 | - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
339 | - React (from `../node_modules/react-native/`)
340 | - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
341 | - React-Core (from `../node_modules/react-native/`)
342 | - React-Core/DevSupport (from `../node_modules/react-native/`)
343 | - React-Core/RCTWebSocket (from `../node_modules/react-native/`)
344 | - React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
345 | - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
346 | - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
347 | - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
348 | - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
349 | - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
350 | - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
351 | - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
352 | - React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
353 | - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
354 | - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
355 | - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
356 | - React-RCTText (from `../node_modules/react-native/Libraries/Text`)
357 | - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
358 | - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
359 | - ReactNativeNavigation (from `../node_modules/react-native-navigation`)
360 | - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
361 |
362 | SPEC REPOS:
363 | trunk:
364 | - boost-for-react-native
365 | - CocoaAsyncSocket
366 | - CocoaLibEvent
367 | - Flipper
368 | - Flipper-DoubleConversion
369 | - Flipper-Folly
370 | - Flipper-Glog
371 | - Flipper-PeerTalk
372 | - Flipper-RSocket
373 | - FlipperKit
374 | - OpenSSL-Universal
375 | - YogaKit
376 |
377 | EXTERNAL SOURCES:
378 | DoubleConversion:
379 | :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
380 | FBLazyVector:
381 | :path: "../node_modules/react-native/Libraries/FBLazyVector"
382 | FBReactNativeSpec:
383 | :path: "../node_modules/react-native/Libraries/FBReactNativeSpec"
384 | Folly:
385 | :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
386 | glog:
387 | :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
388 | RCTRequired:
389 | :path: "../node_modules/react-native/Libraries/RCTRequired"
390 | RCTTypeSafety:
391 | :path: "../node_modules/react-native/Libraries/TypeSafety"
392 | React:
393 | :path: "../node_modules/react-native/"
394 | React-callinvoker:
395 | :path: "../node_modules/react-native/ReactCommon/callinvoker"
396 | React-Core:
397 | :path: "../node_modules/react-native/"
398 | React-CoreModules:
399 | :path: "../node_modules/react-native/React/CoreModules"
400 | React-cxxreact:
401 | :path: "../node_modules/react-native/ReactCommon/cxxreact"
402 | React-jsi:
403 | :path: "../node_modules/react-native/ReactCommon/jsi"
404 | React-jsiexecutor:
405 | :path: "../node_modules/react-native/ReactCommon/jsiexecutor"
406 | React-jsinspector:
407 | :path: "../node_modules/react-native/ReactCommon/jsinspector"
408 | React-RCTActionSheet:
409 | :path: "../node_modules/react-native/Libraries/ActionSheetIOS"
410 | React-RCTAnimation:
411 | :path: "../node_modules/react-native/Libraries/NativeAnimation"
412 | React-RCTBlob:
413 | :path: "../node_modules/react-native/Libraries/Blob"
414 | React-RCTImage:
415 | :path: "../node_modules/react-native/Libraries/Image"
416 | React-RCTLinking:
417 | :path: "../node_modules/react-native/Libraries/LinkingIOS"
418 | React-RCTNetwork:
419 | :path: "../node_modules/react-native/Libraries/Network"
420 | React-RCTSettings:
421 | :path: "../node_modules/react-native/Libraries/Settings"
422 | React-RCTText:
423 | :path: "../node_modules/react-native/Libraries/Text"
424 | React-RCTVibration:
425 | :path: "../node_modules/react-native/Libraries/Vibration"
426 | ReactCommon:
427 | :path: "../node_modules/react-native/ReactCommon"
428 | ReactNativeNavigation:
429 | :path: "../node_modules/react-native-navigation"
430 | Yoga:
431 | :path: "../node_modules/react-native/ReactCommon/yoga"
432 |
433 | SPEC CHECKSUMS:
434 | boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
435 | CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
436 | CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
437 | DoubleConversion: cde416483dac037923206447da6e1454df403714
438 | FBLazyVector: 878b59e31113e289e275165efbe4b54fa614d43d
439 | FBReactNativeSpec: 7da9338acfb98d4ef9e5536805a0704572d33c2f
440 | Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
441 | Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
442 | Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a
443 | Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
444 | Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
445 | Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
446 | FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d
447 | Folly: b73c3869541e86821df3c387eb0af5f65addfab4
448 | glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
449 | OpenSSL-Universal: ff34003318d5e1163e9529b08470708e389ffcdd
450 | RCTRequired: 48884c74035a0b5b76dbb7a998bd93bcfc5f2047
451 | RCTTypeSafety: edf4b618033c2f1c5b7bc3d90d8e085ed95ba2ab
452 | React: f36e90f3ceb976546e97df3403e37d226f79d0e3
453 | React-callinvoker: 18874f621eb96625df7a24a7dc8d6e07391affcd
454 | React-Core: ac3d816b8e3493970153f4aaf0cff18af0bb95e6
455 | React-CoreModules: 4016d3a4e518bcfc4f5a51252b5a05692ca6f0e1
456 | React-cxxreact: ffc9129013b87cb36cf3f30a86695a3c397b0f99
457 | React-jsi: df07aa95b39c5be3e41199921509bfa929ed2b9d
458 | React-jsiexecutor: b56c03e61c0dd5f5801255f2160a815f4a53d451
459 | React-jsinspector: 8e68ffbfe23880d3ee9bafa8be2777f60b25cbe2
460 | React-RCTActionSheet: 53ea72699698b0b47a6421cb1c8b4ab215a774aa
461 | React-RCTAnimation: 1befece0b5183c22ae01b966f5583f42e69a83c2
462 | React-RCTBlob: 0b284339cbe4b15705a05e2313a51c6d8b51fa40
463 | React-RCTImage: d1756599ebd4dc2cb19d1682fe67c6b976658387
464 | React-RCTLinking: 9af0a51c6d6a4dd1674daadafffc6d03033a6d18
465 | React-RCTNetwork: 332c83929cc5eae0b3bbca4add1d668e1fc18bda
466 | React-RCTSettings: d6953772cfd55f2c68ad72b7ef29efc7ec49f773
467 | React-RCTText: 65a6de06a7389098ce24340d1d3556015c38f746
468 | React-RCTVibration: 8e9fb25724a0805107fc1acc9075e26f814df454
469 | ReactCommon: 4167844018c9ed375cc01a843e9ee564399e53c3
470 | ReactNativeNavigation: c2dcda2b86e32090c443182206c915107d03106f
471 | Yoga: 7d13633d129fd179e01b8953d38d47be90db185a
472 | YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
473 |
474 | PODFILE CHECKSUM: 25cec2777a38e06f777b15a78e1658c4214b6b68
475 |
476 | COCOAPODS: 1.10.0
477 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | module.exports = {
9 | transformer: {
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: false,
14 | },
15 | }),
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rnn-drawer-example",
3 | "version": "0.0.1",
4 | "description": "This is an example project for the react-native-navigation-drawer-extension package",
5 | "private": true,
6 | "scripts": {
7 | "android": "react-native run-android",
8 | "ios": "react-native run-ios",
9 | "start": "react-native start",
10 | "test": "jest",
11 | "lint": "eslint ."
12 | },
13 | "dependencies": {
14 | "react": "16.13.1",
15 | "react-native": "0.63.3",
16 | "react-native-navigation": "^7.2.0",
17 | "react-native-navigation-drawer-extension": "^3.2.0"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.8.4",
21 | "@babel/runtime": "^7.8.4",
22 | "@react-native-community/eslint-config": "^1.1.0",
23 | "babel-jest": "^25.1.0",
24 | "eslint": "^6.5.1",
25 | "jest": "^25.1.0",
26 | "metro-react-native-babel-preset": "^0.59.0",
27 | "react-test-renderer": "16.13.1"
28 | },
29 | "jest": {
30 | "preset": "react-native"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/example/src/components/CustomDrawer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {SafeAreaView, StyleSheet, Text, View} from 'react-native';
3 | import DrawerButton from './DrawerButton';
4 |
5 | const Buttons = [
6 | {
7 | id: 1,
8 | name: 'Home Page',
9 | component: 'HomePage',
10 | },
11 | {
12 | id: 2,
13 | name: 'Page 1',
14 | component: 'Page1',
15 | },
16 | {
17 | id: 3,
18 | name: 'Page 2',
19 | component: 'Page2',
20 | },
21 | {
22 | id: 4,
23 | name: 'Another Page',
24 | component: 'AnotherPage',
25 | },
26 | ];
27 |
28 | const CustomDrawer = ({parentComponentId}) => {
29 | return (
30 |
31 |
32 | Custom Drawer
33 |
34 | {Buttons.map((button) => {
35 | return (
36 |
42 | );
43 | })}
44 |
45 |
46 | );
47 | };
48 |
49 | const styles = StyleSheet.create({
50 | mainContainer: {
51 | padding: 20,
52 | },
53 |
54 | bodyText: {
55 | fontSize: 20,
56 | margin: 20,
57 | textAlign: 'center',
58 | },
59 | });
60 |
61 | export default CustomDrawer;
62 |
--------------------------------------------------------------------------------
/example/src/components/DrawerButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, Text, TouchableOpacity} from 'react-native';
3 | import {Navigation} from 'react-native-navigation';
4 | import {RNNDrawer} from 'react-native-navigation-drawer-extension';
5 |
6 | /**
7 | * A workaround to avoid pushing
8 | * the same screen multiple times.
9 | *
10 | * For details, check:
11 | * https://github.com/aspect-apps/react-native-navigation-drawer-extension/issues/31
12 | */
13 |
14 | /**
15 | * We set this to HomePage because,
16 | * in this project, HomePage
17 | * is the initial component.
18 | */
19 | let lastPageName = 'HomePage';
20 | const CurrentComponentName = 'CustomDrawer';
21 |
22 | Navigation.events().registerComponentDidAppearListener((event) => {
23 | if (event.componentName !== CurrentComponentName) {
24 | lastPageName = event.componentName;
25 | }
26 | });
27 |
28 | const DrawerButton = ({name, component, parentComponentId}) => {
29 | const handleOpenPage = () => {
30 | RNNDrawer.dismissDrawer();
31 |
32 | if (lastPageName === component) {
33 | return;
34 | }
35 |
36 | Navigation.push(parentComponentId, {
37 | component: {
38 | name: component,
39 | },
40 | });
41 | };
42 |
43 | return (
44 |
45 | {name}
46 |
47 | );
48 | };
49 |
50 | const styles = StyleSheet.create({
51 | buttonContainer: {
52 | margin: 5,
53 | padding: 10,
54 | borderRadius: 8,
55 | backgroundColor: '#44475a',
56 | },
57 |
58 | buttonText: {
59 | color: 'white',
60 | textAlign: 'center',
61 | fontSize: 18,
62 | },
63 | });
64 |
65 | export default DrawerButton;
66 |
--------------------------------------------------------------------------------
/example/src/pages/AnotherPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { StyleSheet, Text } from 'react-native';
3 | import { SideMenuView } from 'react-native-navigation-drawer-extension';
4 |
5 | const AnotherPage = (props) => {
6 | console.log(props);
7 | return (
8 |
16 |
17 | In this page, you can try the SideMenuView component, by simply swiping
18 | from the right to the left.
19 |
20 |
21 | );
22 | };
23 |
24 | const styles = StyleSheet.create({
25 | mainContainer: {
26 | padding: 20,
27 | backgroundColor: 'white',
28 | flex: 1,
29 | },
30 |
31 | bodyText: {
32 | fontSize: 20,
33 | },
34 | });
35 |
36 | export default AnotherPage;
37 |
--------------------------------------------------------------------------------
/example/src/pages/HomePage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | SafeAreaView,
4 | StyleSheet,
5 | Text,
6 | TouchableOpacity,
7 | View,
8 | } from 'react-native';
9 | import {
10 | RNNDrawer,
11 | SideMenuView,
12 | } from 'react-native-navigation-drawer-extension';
13 |
14 | const HomePage = (props) => {
15 | const onPress = () => {
16 | RNNDrawer.showDrawer({
17 | component: {
18 | name: 'CustomDrawer',
19 | passProps: {
20 | animationOpenTime: 300,
21 | animationCloseTime: 300,
22 | direction: 'left',
23 | dismissWhenTouchOutside: true,
24 | fadeOpacity: 0.6,
25 | drawerScreenWidth: '75%' || 445,
26 | drawerScreenHeight: '100%' || 700,
27 | parentComponentId: props.componentId,
28 | style: {
29 | backgroundColor: 'white',
30 | },
31 | },
32 | options: {
33 | layout: {
34 | componentBackgroundColor: 'black',
35 | },
36 | },
37 | },
38 | });
39 | };
40 |
41 | return (
42 |
64 |
65 |
66 | HomePage View
67 |
68 |
69 | Open Drawer
70 |
71 |
72 |
73 |
74 | );
75 | };
76 |
77 | const styles = StyleSheet.create({
78 | mainContainer: {
79 | padding: 20,
80 | backgroundColor: 'white',
81 | alignItems: 'center',
82 | },
83 |
84 | headlineText: {
85 | textAlign: 'center',
86 | fontSize: 24,
87 | fontWeight: '700',
88 | },
89 |
90 | buttonContainer: {
91 | width: '90%',
92 | backgroundColor: '#44475a',
93 | borderRadius: 10,
94 | padding: 10,
95 | marginTop: 20,
96 | },
97 |
98 | buttonText: {
99 | fontSize: 20,
100 | color: 'white',
101 | textAlign: 'center',
102 | fontWeight: '600',
103 | textTransform: 'uppercase',
104 | letterSpacing: 1.1,
105 | },
106 | });
107 |
108 | export default HomePage;
109 |
--------------------------------------------------------------------------------
/example/src/pages/Page1.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | SafeAreaView,
4 | StyleSheet,
5 | Text,
6 | TouchableOpacity,
7 | View,
8 | } from 'react-native';
9 | import {RNNDrawer} from 'react-native-navigation-drawer-extension';
10 |
11 | const Page1 = (props) => {
12 | const onPress = () => {
13 | RNNDrawer.showDrawer({
14 | component: {
15 | name: 'CustomDrawer',
16 | passProps: {
17 | direction: 'left',
18 | dismissWhenTouchOutside: true,
19 | fadeOpacity: 0.6,
20 | drawerScreenWidth: '75%' || 445,
21 | drawerScreenHeight: '100%' || 700,
22 | parentComponentId: props.componentId,
23 | },
24 | },
25 | });
26 | };
27 |
28 | return (
29 |
30 |
31 | Page1 View
32 |
33 |
34 | Open Drawer
35 |
36 |
37 |
38 | );
39 | };
40 |
41 | const styles = StyleSheet.create({
42 | mainContainer: {
43 | padding: 20,
44 | backgroundColor: 'white',
45 | alignItems: 'center',
46 | },
47 |
48 | headlineText: {
49 | textAlign: 'center',
50 | fontSize: 24,
51 | fontWeight: '700',
52 | },
53 |
54 | buttonContainer: {
55 | width: '90%',
56 | backgroundColor: '#44475a',
57 | borderRadius: 10,
58 | padding: 10,
59 | marginTop: 20,
60 | },
61 |
62 | buttonText: {
63 | fontSize: 20,
64 | color: 'white',
65 | textAlign: 'center',
66 | fontWeight: '600',
67 | textTransform: 'uppercase',
68 | letterSpacing: 1.1,
69 | },
70 | });
71 |
72 | export default Page1;
73 |
--------------------------------------------------------------------------------
/example/src/pages/Page2.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | SafeAreaView,
4 | StyleSheet,
5 | Text,
6 | TouchableOpacity,
7 | View,
8 | } from 'react-native';
9 | import {RNNDrawer} from 'react-native-navigation-drawer-extension';
10 |
11 | const Page2 = (props) => {
12 | const onPress = () => {
13 | RNNDrawer.showDrawer({
14 | component: {
15 | name: 'CustomDrawer',
16 | passProps: {
17 | direction: 'left',
18 | dismissWhenTouchOutside: true,
19 | fadeOpacity: 0.6,
20 | drawerScreenWidth: '75%' || 445,
21 | drawerScreenHeight: '100%' || 700,
22 | parentComponentId: props.componentId,
23 | },
24 | },
25 | });
26 | };
27 |
28 | return (
29 |
30 |
31 | Page2 View
32 |
33 |
34 | Open Drawer
35 |
36 |
37 |
38 | );
39 | };
40 |
41 | const styles = StyleSheet.create({
42 | mainContainer: {
43 | padding: 20,
44 | backgroundColor: 'white',
45 | alignItems: 'center',
46 | },
47 |
48 | headlineText: {
49 | textAlign: 'center',
50 | fontSize: 24,
51 | fontWeight: '700',
52 | },
53 |
54 | buttonContainer: {
55 | width: '90%',
56 | backgroundColor: '#44475a',
57 | borderRadius: 10,
58 | padding: 10,
59 | marginTop: 20,
60 | },
61 |
62 | buttonText: {
63 | fontSize: 20,
64 | color: 'white',
65 | textAlign: 'center',
66 | fontWeight: '600',
67 | textTransform: 'uppercase',
68 | letterSpacing: 1.1,
69 | },
70 | });
71 |
72 | export default Page2;
73 |
--------------------------------------------------------------------------------
/lib/RNNDrawer.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Luke Brandon Farrell
3 | * @description An animated drawer component for react-native-navigation.
4 | */
5 | import * as React from 'react';
6 | import { Layout } from 'react-native-navigation';
7 | declare interface RNNDrawerOptions {
8 | /**
9 | * Id of parent component of the drawer.
10 | * This field is necessary in order to be able
11 | * to push screens inside the drawer
12 | */
13 | parentComponentId: string;
14 | /**
15 | * Direction to open the collage,
16 | * one of: ["left", "right", "top", "bottom"]
17 | * If not provided, drawer might have
18 | * a weird effect when closing
19 | */
20 | direction?: DirectionType;
21 | /**
22 | * Time in milliseconds to execute the drawer opening animation
23 | */
24 | animationOpenTime?: number;
25 | /**
26 | * Time in milliseconds to execute the drawer closing animation
27 | */
28 | animationCloseTime?: number;
29 | /**
30 | * Whether the drawer be dismissed when a click is registered outside
31 | */
32 | dismissWhenTouchOutside?: boolean;
33 | /**
34 | * Opacity of the screen outside the drawer
35 | */
36 | fadeOpacity?: number;
37 | /**
38 | * Width of drawer on portrait orientation. Pass a string containing '%' (e.g. "80%")
39 | * for setting the width in relation to the screen or a number for absolute width (e.g. 300)
40 | */
41 | drawerScreenWidth?: number | string;
42 | /**
43 | * Width of drawer on landscape orientation. Pass a string containing '%' (e.g. "80%")
44 | * for setting the width in relation to the screen or a number for absolute width (e.g. 300)
45 | */
46 | drawerScreenWidthOnLandscape?: number | string;
47 | /**
48 | * Height of drawer. Pass a string containing '%' (e.g. "30%")
49 | * for setting the height in relation to the screen or a number for absolute height (e.g. 300)
50 | */
51 | drawerScreenHeight?: number | string;
52 | disableDragging?: boolean;
53 | disableSwiping?: boolean;
54 | }
55 | export declare enum DirectionType {
56 | left = "left",
57 | right = "right",
58 | bottom = "bottom",
59 | top = "top"
60 | }
61 | declare class RNNDrawer {
62 | /**
63 | * Generates the drawer component to
64 | * be used with react-native-navigation
65 | *
66 | * @param component
67 | */
68 | static create(Component: React.ComponentType): any;
69 | /**
70 | * Shows a drawer component
71 | *
72 | * @param layout
73 | */
74 | static showDrawer(layout: Layout): void;
75 | /**
76 | * Dismiss the drawer component
77 | */
78 | static dismissDrawer(): void;
79 | }
80 | export default RNNDrawer;
81 |
--------------------------------------------------------------------------------
/lib/RNNDrawer.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @author Luke Brandon Farrell
4 | * @description An animated drawer component for react-native-navigation.
5 | */
6 | var __extends = (this && this.__extends) || (function () {
7 | var extendStatics = function (d, b) {
8 | extendStatics = Object.setPrototypeOf ||
9 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
10 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
11 | return extendStatics(d, b);
12 | };
13 | return function (d, b) {
14 | extendStatics(d, b);
15 | function __() { this.constructor = d; }
16 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
17 | };
18 | })();
19 | var __assign = (this && this.__assign) || function () {
20 | __assign = Object.assign || function(t) {
21 | for (var s, i = 1, n = arguments.length; i < n; i++) {
22 | s = arguments[i];
23 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
24 | t[p] = s[p];
25 | }
26 | return t;
27 | };
28 | return __assign.apply(this, arguments);
29 | };
30 | Object.defineProperty(exports, "__esModule", { value: true });
31 | exports.DirectionType = void 0;
32 | /* NPM - Node Package Manage */
33 | var React = require("react");
34 | var react_native_1 = require("react-native");
35 | var react_native_navigation_1 = require("react-native-navigation");
36 | /* Utils - Project Utilities */
37 | var events_1 = require("./events");
38 | var DirectionType;
39 | (function (DirectionType) {
40 | DirectionType["left"] = "left";
41 | DirectionType["right"] = "right";
42 | DirectionType["bottom"] = "bottom";
43 | DirectionType["top"] = "top";
44 | })(DirectionType = exports.DirectionType || (exports.DirectionType = {}));
45 | var RNNDrawer = /** @class */ (function () {
46 | function RNNDrawer() {
47 | }
48 | /**
49 | * Generates the drawer component to
50 | * be used with react-native-navigation
51 | *
52 | * @param component
53 | */
54 | RNNDrawer.create = function (Component) {
55 | var WrappedDrawer = /** @class */ (function (_super) {
56 | __extends(WrappedDrawer, _super);
57 | /**
58 | * [ Built-in React method. ]
59 | *
60 | * Setup the component. Executes when the component is created
61 | *
62 | * @param {object} props
63 | */
64 | function WrappedDrawer(props) {
65 | var _this = _super.call(this, props) || this;
66 | _this.panningStartedPoint = { moveX: 0, moveY: 0 };
67 | _this.startedFromSideMenu = false;
68 | _this.onOrientationChange = function (_a) {
69 | var window = _a.window;
70 | var screenHeight = window.height;
71 | _this.setState({ screenHeight: screenHeight });
72 | // Apply correct position if opened from right
73 | if (_this.props.direction === 'right') {
74 | // Calculates the position of the drawer from the left side of the screen
75 | var alignedMovementValue = window.width - _this.drawerWidth;
76 | _this.state.sideMenuOpenValue.setValue(alignedMovementValue);
77 | }
78 | };
79 | _this.screenWidth = react_native_1.Dimensions.get('window').width;
80 | _this.screenHeight = react_native_1.Dimensions.get('window').height;
81 | _this.panResponder = react_native_1.PanResponder.create({
82 | onStartShouldSetPanResponder: function (_evt, _gestureState) { return false; },
83 | onStartShouldSetPanResponderCapture: function (_evt, _gestureState) { return false; },
84 | onMoveShouldSetPanResponder: function (_evt, _gestureState) {
85 | var dx = _gestureState.dx, dy = _gestureState.dy;
86 | if (_this.props.direction === DirectionType.left ||
87 | _this.props.direction === DirectionType.right)
88 | return Math.abs(dx) > 5;
89 | else
90 | return Math.abs(dy) > 5;
91 | },
92 | onMoveShouldSetPanResponderCapture: function (_evt, _gestureState) { return false; },
93 | onPanResponderGrant: function (_evt, _gestureState) {
94 | var moveX = _gestureState.moveX, moveY = _gestureState.moveY;
95 | events_1.dispatch('SWIPE_START', { moveX: moveX, moveY: moveY });
96 | },
97 | onPanResponderRelease: function (_evt, gestureState) {
98 | var vx = gestureState.vx;
99 | // Emit this event when the gesture ends
100 | events_1.dispatch('SWIPE_END', vx > 0 ? 'right' : 'left');
101 | },
102 | onPanResponderTerminationRequest: function (_evt, _gestureState) { return false; },
103 | onShouldBlockNativeResponder: function (_evt, _gestureState) { return false; },
104 | onPanResponderMove: function (_evt, _gestureState) {
105 | var moveX = _gestureState.moveX, moveY = _gestureState.moveY;
106 | var direction = _this.props.direction || 'left';
107 | events_1.dispatch('SWIPE_MOVE', { value: { moveX: moveX, moveY: moveY }, direction: direction });
108 | },
109 | });
110 | /*
111 | * We need to convert the pushed drawer width
112 | * to a number as it can either be a string ('20%')
113 | * or number (400).
114 | */
115 | var _resolveDrawerSize = function (value, max) {
116 | /*
117 | * If the type is a string '%' then it should be a percentage relative
118 | * to our max size.
119 | */
120 | if (typeof value === 'string') {
121 | var valueAsNumber = parseFloat(value) || 100;
122 | var size = max * (valueAsNumber / 100);
123 | return size;
124 | }
125 | return value;
126 | };
127 | /** Component Variables */
128 | _this.drawerWidth = _resolveDrawerSize(_this.isLandscape()
129 | ? props.drawerScreenWidthOnLandscape
130 | : props.drawerScreenWidth, _this.screenWidth);
131 | _this.drawerHeight = _resolveDrawerSize(props.drawerScreenHeight, _this.screenHeight);
132 | _this.drawerOpenedValues = {
133 | left: 0,
134 | right: _this.screenWidth - _this.drawerWidth,
135 | top: _this.drawerHeight - _this.screenHeight,
136 | bottom: _this.screenHeight - _this.drawerHeight,
137 | };
138 | _this.initialValues = {
139 | left: -_this.drawerWidth,
140 | right: _this.screenWidth,
141 | top: -_this.screenHeight,
142 | bottom: _this.screenHeight,
143 | };
144 | /** Component State */
145 | _this.state = {
146 | sideMenuOpenValue: new react_native_1.Animated.Value(_this.initialValues[props.direction]),
147 | sideMenuOverlayOpacity: new react_native_1.Animated.Value(0),
148 | sideMenuSwipingStarted: false,
149 | sideMenuIsDismissing: false,
150 | screenHeight: _this.screenHeight,
151 | };
152 | /** Component Bindings */
153 | _this.touchedOutside = _this.touchedOutside.bind(_this);
154 | _this.dismissDrawerWithAnimation = _this.dismissDrawerWithAnimation.bind(_this);
155 | _this.registerListeners = _this.registerListeners.bind(_this);
156 | _this.removeListeners = _this.removeListeners.bind(_this);
157 | _this.isLandscape = _this.isLandscape.bind(_this);
158 | react_native_navigation_1.Navigation.events().bindComponent(_this);
159 | return _this;
160 | }
161 | /**
162 | * Check if device is in landscape mode
163 | */
164 | WrappedDrawer.prototype.isLandscape = function () {
165 | var dim = react_native_1.Dimensions.get('window');
166 | return dim.height <= dim.width;
167 | };
168 | /**
169 | * [ Built-in React method. ]
170 | *
171 | * Executed when the component is mounted to the screen
172 | */
173 | WrappedDrawer.prototype.componentDidMount = function () {
174 | /** Props */
175 | var _a = this.props, direction = _a.direction, fadeOpacity = _a.fadeOpacity, animateDrawerExpanding = _a.animateDrawerExpanding;
176 | if (typeof animateDrawerExpanding !== 'undefined' &&
177 | !animateDrawerExpanding)
178 | this.startedFromSideMenu = true;
179 | // Animate side menu open
180 | this.animatedDrawer = react_native_1.Animated.timing(this.state.sideMenuOpenValue, {
181 | toValue: this.drawerOpenedValues[direction],
182 | duration: this.props.animationOpenTime,
183 | useNativeDriver: true,
184 | });
185 | // Animate outside side menu opacity
186 | this.animatedOpacity = react_native_1.Animated.timing(this.state.sideMenuOverlayOpacity, {
187 | toValue: fadeOpacity,
188 | duration: this.props.animationOpenTime,
189 | useNativeDriver: true,
190 | });
191 | };
192 | /**
193 | * [ react-native-navigation method. ]
194 | *
195 | * Executed when the component is navigated to view.
196 | */
197 | WrappedDrawer.prototype.componentDidAppear = function () {
198 | this.registerListeners();
199 | // If there has been no Swiping, and this component appears, then just start the open animations
200 | if (!this.state.sideMenuSwipingStarted &&
201 | this.props.animateDrawerExpanding) {
202 | this.animatedDrawer.start();
203 | this.animatedOpacity.start();
204 | }
205 | };
206 | /**
207 | * [ react-native-navigation method. ]
208 | *
209 | * Executed when the component is navigated away from view.
210 | */
211 | WrappedDrawer.prototype.componentDidDisappear = function () {
212 | this.removeListeners();
213 | events_1.dispatch('DRAWER_CLOSED');
214 | };
215 | /**
216 | * Registers all the listenrs for this component
217 | */
218 | WrappedDrawer.prototype.registerListeners = function () {
219 | var _this = this;
220 | /** Props */
221 | var _a = this.props, direction = _a.direction, fadeOpacity = _a.fadeOpacity;
222 | // Adapt the drawer's size on orientation change
223 | this.orientationChangeListener = react_native_1.Dimensions.addEventListener('change', this.onOrientationChange);
224 | // Executes when the side of the screen interaction starts
225 | this.unsubscribeSwipeStart = events_1.listen('SWIPE_START', function (value) {
226 | _this.panningStartedPoint.moveX = value.moveX;
227 | _this.panningStartedPoint.moveY = value.moveY;
228 | _this.setState({
229 | sideMenuSwipingStarted: true,
230 | });
231 | });
232 | // Executes when the side of the screen is interacted with
233 | this.unsubscribeSwipeMove = events_1.listen('SWIPE_MOVE', function (_a) {
234 | var value = _a.value, swipeDirection = _a.direction;
235 | // Cover special case when we are swiping from the edge of the screen
236 | if (_this.startedFromSideMenu) {
237 | if (direction === 'left' && value.moveX < _this.drawerWidth) {
238 | _this.state.sideMenuOpenValue.setValue(value.moveX - _this.drawerWidth);
239 | var normalizedOpacity_1 = Math.min((value.moveX / _this.drawerWidth) * fadeOpacity, fadeOpacity);
240 | _this.state.sideMenuOverlayOpacity.setValue(normalizedOpacity_1);
241 | }
242 | if (direction === 'right' &&
243 | _this.screenWidth - value.moveX < _this.drawerWidth) {
244 | _this.state.sideMenuOpenValue.setValue(value.moveX);
245 | var normalizedOpacity_2 = Math.min(((_this.screenWidth - value.moveX) / _this.drawerWidth) *
246 | fadeOpacity, fadeOpacity);
247 | _this.state.sideMenuOverlayOpacity.setValue(normalizedOpacity_2);
248 | }
249 | return;
250 | }
251 | if (_this.props.disableDragging)
252 | return;
253 | // Calculates the translateX / translateY value
254 | var alignedMovementValue = 0;
255 | // To swap the direction if needed
256 | var directionModifier = 1;
257 | // Whether we use the height of the drawer or the width
258 | var drawerDimension = _this.drawerWidth;
259 | if (swipeDirection === 'left') {
260 | alignedMovementValue =
261 | value.moveX - _this.panningStartedPoint.moveX;
262 | }
263 | else if (swipeDirection === 'right') {
264 | alignedMovementValue =
265 | _this.panningStartedPoint.moveX - value.moveX;
266 | directionModifier = -1;
267 | }
268 | else if (swipeDirection === 'bottom') {
269 | alignedMovementValue =
270 | _this.panningStartedPoint.moveY - value.moveY;
271 | directionModifier = -1;
272 | drawerDimension = _this.drawerHeight;
273 | }
274 | else if (swipeDirection === 'top') {
275 | alignedMovementValue =
276 | value.moveY - _this.panningStartedPoint.moveY;
277 | drawerDimension = _this.drawerHeight;
278 | }
279 | // Calculates the percentage 0 - 1 of which the drawer is open
280 | var openedPercentage = Math.abs(drawerDimension + alignedMovementValue) /
281 | drawerDimension;
282 | // Calculates the opacity to set of the screen based on the percentage the drawer is open
283 | var normalizedOpacity = Math.min(openedPercentage * fadeOpacity, fadeOpacity);
284 | // Does not allow the drawer to go further than the maximum width / height
285 | if (0 > alignedMovementValue) {
286 | // Sets the animation values, we use this so we can resume animation from any point
287 | _this.state.sideMenuOpenValue.setValue(_this.drawerOpenedValues[direction] +
288 | alignedMovementValue * directionModifier);
289 | _this.state.sideMenuOverlayOpacity.setValue(normalizedOpacity);
290 | }
291 | });
292 | // Executes when the side of the screen interaction ends
293 | this.unsubscribeSwipeEnd = events_1.listen('SWIPE_END', function (swipeDirection) {
294 | if (_this.props.disableSwiping && !_this.startedFromSideMenu)
295 | return;
296 | var reverseDirection = {
297 | right: 'left',
298 | left: 'right',
299 | top: 'bottom',
300 | bottom: 'top',
301 | };
302 | // In case the drawer started by dragging the edge of the screen reset the flag
303 | _this.startedFromSideMenu = false;
304 | if (swipeDirection === reverseDirection[direction]) {
305 | _this.animatedDrawer.start();
306 | _this.animatedOpacity.start();
307 | }
308 | else {
309 | if (!_this.state.sideMenuIsDismissing) {
310 | _this.setState({
311 | sideMenuIsDismissing: true,
312 | }, function () {
313 | _this.dismissDrawerWithAnimation();
314 | });
315 | }
316 | }
317 | });
318 | // Executes when the drawer needs to be dismissed
319 | this.unsubscribeDismissDrawer = events_1.listen('DISMISS_DRAWER', function () {
320 | if (!_this.state.sideMenuIsDismissing) {
321 | _this.dismissDrawerWithAnimation();
322 | }
323 | });
324 | };
325 | /**
326 | * Removes all the listenrs from this component
327 | */
328 | WrappedDrawer.prototype.removeListeners = function () {
329 | if (this.orientationChangeListener)
330 | this.orientationChangeListener.remove();
331 | if (this.unsubscribeSwipeStart)
332 | this.unsubscribeSwipeStart();
333 | if (this.unsubscribeSwipeMove)
334 | this.unsubscribeSwipeMove();
335 | if (this.unsubscribeSwipeEnd)
336 | this.unsubscribeSwipeEnd();
337 | if (this.unsubscribeDismissDrawer)
338 | this.unsubscribeDismissDrawer();
339 | };
340 | /**
341 | * [ Built-in React method. ]
342 | *
343 | * Allows us to render JSX to the screen
344 | */
345 | WrappedDrawer.prototype.render = function () {
346 | /** Styles */
347 | var sideMenuOverlayStyle = styles.sideMenuOverlayStyle, sideMenuContainerStyle = styles.sideMenuContainerStyle;
348 | /** Props */
349 | var _a = this.props, direction = _a.direction, style = _a.style;
350 | /** State */
351 | var _b = this.state, sideMenuOpenValue = _b.sideMenuOpenValue, sideMenuOverlayOpacity = _b.sideMenuOverlayOpacity;
352 | /** Variables */
353 | var animatedValue = direction === DirectionType.left || direction === DirectionType.right
354 | ? { translateX: sideMenuOpenValue }
355 | : { translateY: sideMenuOpenValue };
356 | return (React.createElement(react_native_1.View, __assign({ style: sideMenuContainerStyle }, this.panResponder.panHandlers),
357 | React.createElement(react_native_1.TouchableWithoutFeedback, { onPress: this.touchedOutside },
358 | React.createElement(react_native_1.Animated.View, { style: [
359 | sideMenuOverlayStyle,
360 | { opacity: sideMenuOverlayOpacity },
361 | ] })),
362 | React.createElement(react_native_1.Animated.View, { style: [
363 | { backgroundColor: '#FFF' },
364 | style,
365 | {
366 | height: this.state.screenHeight,
367 | width: this.drawerWidth,
368 | transform: [animatedValue],
369 | },
370 | ] },
371 | React.createElement(Component, __assign({}, this.props)))));
372 | };
373 | /**
374 | * Touched outside drawer
375 | */
376 | WrappedDrawer.prototype.touchedOutside = function () {
377 | var dismissWhenTouchOutside = this.props.dismissWhenTouchOutside;
378 | if (dismissWhenTouchOutside) {
379 | this.dismissDrawerWithAnimation();
380 | }
381 | };
382 | /**
383 | * Dismisses drawer with animation
384 | */
385 | WrappedDrawer.prototype.dismissDrawerWithAnimation = function () {
386 | var _this = this;
387 | var direction = this.props.direction;
388 | var sideMenuIsDismissing = this.state.sideMenuIsDismissing;
389 | var closeValues = {
390 | left: -this.drawerWidth,
391 | right: this.screenWidth,
392 | top: -this.screenHeight,
393 | bottom: this.screenHeight,
394 | };
395 | // Animate side menu close
396 | react_native_1.Animated.timing(this.state.sideMenuOpenValue, {
397 | toValue: closeValues[direction],
398 | duration: this.props.animationCloseTime,
399 | useNativeDriver: true,
400 | }).start(function () {
401 | react_native_navigation_1.Navigation.dismissOverlay(_this.props.componentId);
402 | _this.setState({ sideMenuIsDismissing: false });
403 | });
404 | // Animate outside side menu opacity
405 | react_native_1.Animated.timing(this.state.sideMenuOverlayOpacity, {
406 | toValue: 0,
407 | duration: this.props.animationCloseTime,
408 | useNativeDriver: true,
409 | }).start();
410 | };
411 | WrappedDrawer.defaultProps = {
412 | animationOpenTime: 300,
413 | animationCloseTime: 300,
414 | direction: 'left',
415 | dismissWhenTouchOutside: true,
416 | fadeOpacity: 0.6,
417 | drawerScreenWidth: '80%',
418 | drawerScreenWidthOnLandscape: '30%',
419 | drawerScreenHeight: '100%',
420 | animateDrawerExpanding: true,
421 | disableDragging: false,
422 | disableSwiping: false,
423 | };
424 | return WrappedDrawer;
425 | }(React.Component));
426 | return WrappedDrawer;
427 | };
428 | /**
429 | * Shows a drawer component
430 | *
431 | * @param layout
432 | */
433 | RNNDrawer.showDrawer = function (layout) {
434 | var _a, _b, _c, _d, _e;
435 | // By default for this library, we make the 'componentBackgroundColor' transparent
436 | var componentBackgroundColor = (_d = (_c = (_b = (_a = layout === null || layout === void 0 ? void 0 : layout.component) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.layout) === null || _c === void 0 ? void 0 : _c.componentBackgroundColor) !== null && _d !== void 0 ? _d : 'transparent';
437 | var options = __assign(__assign({}, (_e = layout === null || layout === void 0 ? void 0 : layout.component) === null || _e === void 0 ? void 0 : _e.options), { layout: {
438 | componentBackgroundColor: componentBackgroundColor,
439 | } });
440 | // Mutate options to add 'transparent' by default
441 | // @ts-ignore
442 | layout.component.options = __assign({}, options);
443 | react_native_navigation_1.Navigation.showOverlay(layout);
444 | };
445 | /**
446 | * Dismiss the drawer component
447 | */
448 | RNNDrawer.dismissDrawer = function () {
449 | events_1.dispatch('DISMISS_DRAWER', true);
450 | };
451 | return RNNDrawer;
452 | }());
453 | exports.default = RNNDrawer;
454 | /** -------------------------------------------- */
455 | /** Component Styling */
456 | /** -------------------------------------------- */
457 | var styles = react_native_1.StyleSheet.create({
458 | sideMenuContainerStyle: {
459 | flex: 1,
460 | flexDirection: 'row',
461 | },
462 | sideMenuOverlayStyle: {
463 | position: 'absolute',
464 | width: '100%',
465 | height: '100%',
466 | backgroundColor: '#000',
467 | },
468 | });
469 |
--------------------------------------------------------------------------------
/lib/SideMenuView.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Luke Brandon Farrell
3 | * @title SideMenuView.js
4 | * @description A swipeable view to open a drawer.
5 | */
6 | import * as React from 'react';
7 | import { StyleProp, ViewStyle } from 'react-native';
8 | import { Options } from 'react-native-navigation';
9 | interface IProps {
10 | swipeSensitivity?: number;
11 | sideMargin?: number;
12 | sideMarginLeft?: number;
13 | sideMarginRight?: number;
14 | style?: StyleProp;
15 | drawerName: string;
16 | direction: 'left' | 'right';
17 | passProps?: any;
18 | options?: Options;
19 | }
20 | declare class SideMenuView extends React.Component {
21 | private isOpened;
22 | private _panResponderMethods;
23 | private _leftPanResponder;
24 | private _rightPanResponder;
25 | private unsubscribeDrawerClosed;
26 | static defaultProps: {
27 | sideMargin: number;
28 | swipeSensitivity: number;
29 | direction: string;
30 | };
31 | /**
32 | * [ Built-in React method. ]
33 | *
34 | * Setup the component. Executes when the component is created
35 | *
36 | * @param {object} props
37 | */
38 | constructor(props: IProps);
39 | /**
40 | * [ Built-in React method. ]
41 | *
42 | * Executed when the component is mounted to the screen
43 | */
44 | componentDidMount(): void;
45 | /**
46 | * Registers all the listenrs for this component
47 | */
48 | registerListeners(): void;
49 | /**
50 | * Removes all the listenrs from this component
51 | */
52 | removeListeners(): void;
53 | /**
54 | * [ Built-in React method. ]
55 | *
56 | * Allows us to render JSX to the screen
57 | */
58 | render(): JSX.Element;
59 | }
60 | export default SideMenuView;
61 |
--------------------------------------------------------------------------------
/lib/SideMenuView.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @author Luke Brandon Farrell
4 | * @title SideMenuView.js
5 | * @description A swipeable view to open a drawer.
6 | */
7 | var __extends = (this && this.__extends) || (function () {
8 | var extendStatics = function (d, b) {
9 | extendStatics = Object.setPrototypeOf ||
10 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
11 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
12 | return extendStatics(d, b);
13 | };
14 | return function (d, b) {
15 | extendStatics(d, b);
16 | function __() { this.constructor = d; }
17 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
18 | };
19 | })();
20 | var __assign = (this && this.__assign) || function () {
21 | __assign = Object.assign || function(t) {
22 | for (var s, i = 1, n = arguments.length; i < n; i++) {
23 | s = arguments[i];
24 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
25 | t[p] = s[p];
26 | }
27 | return t;
28 | };
29 | return __assign.apply(this, arguments);
30 | };
31 | var __rest = (this && this.__rest) || function (s, e) {
32 | var t = {};
33 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
34 | t[p] = s[p];
35 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
36 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
37 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
38 | t[p[i]] = s[p[i]];
39 | }
40 | return t;
41 | };
42 | Object.defineProperty(exports, "__esModule", { value: true });
43 | /* NPM - Node Package Manage */
44 | var React = require("react");
45 | var react_native_1 = require("react-native");
46 | /* Utils - Project Utilities */
47 | var RNNDrawer_1 = require("./RNNDrawer");
48 | var events_1 = require("./events");
49 | var RNNDrawer_2 = require("./RNNDrawer");
50 | var screenHeight = react_native_1.Dimensions.get('screen').height;
51 | var SideMenuView = /** @class */ (function (_super) {
52 | __extends(SideMenuView, _super);
53 | /**
54 | * [ Built-in React method. ]
55 | *
56 | * Setup the component. Executes when the component is created
57 | *
58 | * @param {object} props
59 | */
60 | function SideMenuView(props) {
61 | var _this = _super.call(this, props) || this;
62 | _this.isOpened = false;
63 | var swipeSensitivity = props.swipeSensitivity, drawerName = props.drawerName, direction = props.direction, passProps = props.passProps, options = props.options;
64 | var directionIsLeft = direction ? direction == 'left' : true;
65 | _this._panResponderMethods = {
66 | // Ask to be the responder:
67 | onStartShouldSetPanResponder: function (_evt, _gestureState) { return true; },
68 | onStartShouldSetPanResponderCapture: function (_evt, _gestureState) { return true; },
69 | onMoveShouldSetPanResponder: function (_evt, _gestureState) { return true; },
70 | onMoveShouldSetPanResponderCapture: function (_evt, _gestureState) { return true; },
71 | onPanResponderGrant: function (_evt, _gestureState) {
72 | events_1.dispatch('SWIPE_START');
73 | },
74 | onPanResponderRelease: function (_evt, gestureState) {
75 | var vx = gestureState.vx;
76 | // Emit this event when the gesture ends
77 | events_1.dispatch('SWIPE_END', vx > 0 ? 'right' : 'left');
78 | },
79 | onPanResponderTerminationRequest: function (_evt, _gestureState) { return false; },
80 | onShouldBlockNativeResponder: function (_evt, _gestureState) { return false; },
81 | };
82 | // LEFT PAN RESPONDER
83 | _this._leftPanResponder = react_native_1.PanResponder.create(__assign(__assign({}, _this._panResponderMethods), { onPanResponderMove: function (_evt, gestureState) {
84 | var moveX = gestureState.moveX, vx = gestureState.vx;
85 | // Emit this event on movement
86 | events_1.dispatch('SWIPE_MOVE', { value: { moveX: moveX }, direction: 'left' });
87 | // Left Swipe
88 | if (typeof swipeSensitivity !== 'undefined') {
89 | if (vx > swipeSensitivity && !_this.isOpened && directionIsLeft) {
90 | _this.isOpened = true;
91 | RNNDrawer_1.default.showDrawer({
92 | component: {
93 | name: drawerName,
94 | passProps: __assign({ direction: RNNDrawer_2.DirectionType.left, parentComponentId: passProps === null || passProps === void 0 ? void 0 : passProps.parentComponentId, animateDrawerExpanding: false }, passProps),
95 | options: __assign({}, options),
96 | },
97 | });
98 | }
99 | }
100 | } }));
101 | // RIGHT PAN RESPONDER
102 | _this._rightPanResponder = react_native_1.PanResponder.create(__assign(__assign({}, _this._panResponderMethods), { onPanResponderMove: function (_evt, gestureState) {
103 | var moveX = gestureState.moveX, vx = gestureState.vx;
104 | // Emit this event on movement
105 | events_1.dispatch('SWIPE_MOVE', { value: { moveX: moveX }, direction: 'right' });
106 | // Right Swipe
107 | if (typeof swipeSensitivity !== 'undefined') {
108 | if (vx > -swipeSensitivity && !_this.isOpened && !directionIsLeft) {
109 | _this.isOpened = true;
110 | RNNDrawer_1.default.showDrawer({
111 | component: {
112 | name: drawerName,
113 | passProps: __assign({ direction: RNNDrawer_2.DirectionType.right, parentComponentId: passProps === null || passProps === void 0 ? void 0 : passProps.parentComponentId, animateDrawerExpanding: false }, passProps),
114 | options: __assign({}, options),
115 | },
116 | });
117 | }
118 | }
119 | } }));
120 | _this.registerListeners = _this.registerListeners.bind(_this);
121 | _this.removeListeners = _this.removeListeners.bind(_this);
122 | return _this;
123 | }
124 | /**
125 | * [ Built-in React method. ]
126 | *
127 | * Executed when the component is mounted to the screen
128 | */
129 | SideMenuView.prototype.componentDidMount = function () {
130 | this.registerListeners();
131 | };
132 | /**
133 | * Registers all the listenrs for this component
134 | */
135 | SideMenuView.prototype.registerListeners = function () {
136 | var _this = this;
137 | // Event fires when drawer is closed
138 | this.unsubscribeDrawerClosed = events_1.listen('DRAWER_CLOSED', function () {
139 | _this.isOpened = false;
140 | });
141 | };
142 | /**
143 | * Removes all the listenrs from this component
144 | */
145 | SideMenuView.prototype.removeListeners = function () {
146 | this.unsubscribeDrawerClosed();
147 | };
148 | /**
149 | * [ Built-in React method. ]
150 | *
151 | * Allows us to render JSX to the screen
152 | */
153 | SideMenuView.prototype.render = function () {
154 | /** Props */
155 | var _a = this.props, children = _a.children, direction = _a.direction, sideMargin = _a.sideMargin, sideMarginLeft = _a.sideMarginLeft, sideMarginRight = _a.sideMarginRight, props = __rest(_a, ["children", "direction", "sideMargin", "sideMarginLeft", "sideMarginRight"]);
156 | var directionIsLeft = direction ? direction == 'left' : true;
157 | return (React.createElement(react_native_1.View, __assign({}, props),
158 | children,
159 | directionIsLeft ? (React.createElement(react_native_1.View, __assign({ style: {
160 | left: 0,
161 | position: 'absolute',
162 | width: sideMargin || sideMarginLeft,
163 | height: screenHeight,
164 | zIndex: 9999,
165 | } }, this._leftPanResponder.panHandlers))) : (React.createElement(react_native_1.View, __assign({ style: {
166 | position: 'absolute',
167 | right: 0,
168 | width: sideMargin || sideMarginRight,
169 | height: screenHeight,
170 | zIndex: 9999,
171 | } }, this._rightPanResponder.panHandlers)))));
172 | };
173 | SideMenuView.defaultProps = {
174 | sideMargin: 15,
175 | swipeSensitivity: 0.2,
176 | direction: 'left',
177 | };
178 | return SideMenuView;
179 | }(React.Component));
180 | exports.default = SideMenuView;
181 |
--------------------------------------------------------------------------------
/lib/events.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Luke Brandon Farrell
3 | * @description Event dispatcher for comunication between components.
4 | */
5 | /**
6 | * @description add listener
7 | * @public
8 | * @param {string} name name listener
9 | * @param {function} func function for call
10 | * @returns {function} unsubscribe function
11 | */
12 | export declare function listen(name: string, func: any): () => void;
13 | /**
14 | * @description dispatch to listener
15 | * @public
16 | * @param {string} name name listener
17 | * @param {any} arg argument for send to listen(...)
18 | * @returns {void}
19 | */
20 | export declare function dispatch(name: string, arg?: any): void;
21 |
--------------------------------------------------------------------------------
/lib/events.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @author Luke Brandon Farrell
4 | * @description Event dispatcher for comunication between components.
5 | */
6 | Object.defineProperty(exports, "__esModule", { value: true });
7 | exports.dispatch = exports.listen = void 0;
8 | /**
9 | * @description events
10 | * @private
11 | */
12 | var _events = {};
13 | /**
14 | * @description add listener
15 | * @public
16 | * @param {string} name name listener
17 | * @param {function} func function for call
18 | * @returns {function} unsubscribe function
19 | */
20 | function listen(name, func) {
21 | if (!_events[name])
22 | _events[name] = { count: 0, funcs: {} };
23 | var key = _events[name].count++;
24 | _events[name].funcs[key] = func;
25 | return function () {
26 | delete _events[name].funcs[key];
27 | };
28 | }
29 | exports.listen = listen;
30 | /**
31 | * @description dispatch to listener
32 | * @public
33 | * @param {string} name name listener
34 | * @param {any} arg argument for send to listen(...)
35 | * @returns {void}
36 | */
37 | function dispatch(name, arg) {
38 | if (_events[name])
39 | for (var func in _events[name].funcs)
40 | _events[name].funcs[func] && _events[name].funcs[func](arg);
41 | }
42 | exports.dispatch = dispatch;
43 |
--------------------------------------------------------------------------------
/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | export { default as RNNDrawer } from './RNNDrawer';
2 | export { default as SideMenuView } from './SideMenuView';
3 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var RNNDrawer_1 = require("./RNNDrawer");
4 | Object.defineProperty(exports, "RNNDrawer", { enumerable: true, get: function () { return RNNDrawer_1.default; } });
5 | var SideMenuView_1 = require("./SideMenuView");
6 | Object.defineProperty(exports, "SideMenuView", { enumerable: true, get: function () { return SideMenuView_1.default; } });
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-navigation-drawer-extension",
3 | "version": "4.0.1",
4 | "description": "Drawer API built on top of wix react-native-navigation for iOS and Android.",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "files": [
8 | "lib/**/*"
9 | ],
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\"",
12 | "prepublishOnly": "pinst --disable",
13 | "postpublish": "pinst --enable",
14 | "pre-commit": "lint-staged",
15 | "postinstall": "husky install"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/lukebrandonfarrell/wix-react-native-navigation-drawer.git"
20 | },
21 | "keywords": [
22 | "wix",
23 | "react-native-navigation",
24 | "navigation",
25 | "react-native",
26 | "drawer",
27 | "side-menu",
28 | "ios",
29 | "android",
30 | "native",
31 | "typescript"
32 | ],
33 | "peerDependencies": {
34 | "react-native-navigation": ">= 3.x"
35 | },
36 | "author": "Luke Brandon Farrell",
37 | "license": "MIT",
38 | "bugs": {
39 | "url": "https://github.com/lukebrandonfarrell/wix-react-native-navigation-drawer/issues"
40 | },
41 | "homepage": "https://github.com/lukebrandonfarrell/wix-react-native-navigation-drawer#readme",
42 | "dependencies": {},
43 | "devDependencies": {
44 | "@commitlint/cli": "^12.1.4",
45 | "@commitlint/config-conventional": "^12.1.4",
46 | "@types/react": "^16.9.1",
47 | "@types/react-native": "^0.70",
48 | "husky": "^6.0.0",
49 | "lint-staged": "^11.0.0",
50 | "pinst": "^2.1.6",
51 | "prettier": "^2.0.4",
52 | "react": "^16.9.0",
53 | "react-native": "^0.62.3",
54 | "react-native-navigation": "^6.4.0",
55 | "semantic-release": "^17.4.3",
56 | "typescript": "^3.9.9"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "printWidth": 80,
3 | "trailingComma": "all",
4 | "singleQuote": true
5 | }
--------------------------------------------------------------------------------
/src/RNNDrawer.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Luke Brandon Farrell
3 | * @description An animated drawer component for react-native-navigation.
4 | */
5 |
6 | /* NPM - Node Package Manage */
7 | import * as React from 'react';
8 | import {
9 | View,
10 | Animated,
11 | Dimensions,
12 | TouchableWithoutFeedback,
13 | StyleSheet,
14 | ViewStyle,
15 | ImageStyle,
16 | PanResponderInstance,
17 | PanResponder,
18 | PanResponderGestureState,
19 | GestureResponderEvent,
20 | EmitterSubscription,
21 | } from 'react-native';
22 | import { Navigation, Layout } from 'react-native-navigation';
23 | /* Utils - Project Utilities */
24 | import { listen, dispatch } from './events';
25 |
26 | declare interface RNNDrawerOptions {
27 | /**
28 | * Id of parent component of the drawer.
29 | * This field is necessary in order to be able
30 | * to push screens inside the drawer
31 | */
32 | parentComponentId: string;
33 |
34 | /**
35 | * Direction to open the collage,
36 | * one of: ["left", "right", "top", "bottom"]
37 | * If not provided, drawer might have
38 | * a weird effect when closing
39 | */
40 | direction?: DirectionType;
41 |
42 | /**
43 | * Time in milliseconds to execute the drawer opening animation
44 | */
45 | animationOpenTime?: number;
46 |
47 | /**
48 | * Time in milliseconds to execute the drawer closing animation
49 | */
50 | animationCloseTime?: number;
51 |
52 | /**
53 | * Whether the drawer be dismissed when a click is registered outside
54 | */
55 | dismissWhenTouchOutside?: boolean;
56 |
57 | /**
58 | * Opacity of the screen outside the drawer
59 | */
60 | fadeOpacity?: number;
61 |
62 | /**
63 | * Width of drawer on portrait orientation. Pass a string containing '%' (e.g. "80%")
64 | * for setting the width in relation to the screen or a number for absolute width (e.g. 300)
65 | */
66 | drawerScreenWidth?: number | string;
67 |
68 | /**
69 | * Width of drawer on landscape orientation. Pass a string containing '%' (e.g. "80%")
70 | * for setting the width in relation to the screen or a number for absolute width (e.g. 300)
71 | */
72 | drawerScreenWidthOnLandscape?: number | string;
73 |
74 | /**
75 | * Height of drawer. Pass a string containing '%' (e.g. "30%")
76 | * for setting the height in relation to the screen or a number for absolute height (e.g. 300)
77 | */
78 | drawerScreenHeight?: number | string;
79 |
80 | disableDragging?: boolean;
81 |
82 | disableSwiping?: boolean;
83 | }
84 |
85 | export enum DirectionType {
86 | left = 'left',
87 | right = 'right',
88 | bottom = 'bottom',
89 | top = 'top',
90 | }
91 |
92 | interface Point {
93 | moveX: number;
94 | moveY: number;
95 | }
96 |
97 | interface IState {
98 | sideMenuOpenValue: Animated.Value;
99 | sideMenuOverlayOpacity: Animated.Value;
100 | sideMenuSwipingStarted: boolean;
101 | sideMenuIsDismissing: boolean;
102 | screenHeight: number;
103 | }
104 |
105 | interface IProps {
106 | /** react-native-navigation */
107 | componentId: string;
108 | /** Props */
109 | animationOpenTime: number;
110 | animationCloseTime: number;
111 | direction: DirectionType;
112 | dismissWhenTouchOutside: boolean;
113 | fadeOpacity: number;
114 | drawerScreenWidth: number | string;
115 | drawerScreenWidthOnLandscape: number | string;
116 | drawerScreenHeight: number | string;
117 | animateDrawerExpanding?: boolean;
118 | disableDragging?: boolean;
119 | disableSwiping?: boolean;
120 | style: any;
121 | }
122 |
123 | interface HOCProps {
124 | Component: React.ComponentType;
125 | }
126 |
127 | interface StylesInterface {
128 | sideMenuContainerStyle: ViewStyle;
129 | sideMenuOverlayStyle: ImageStyle;
130 | }
131 |
132 | interface DrawerDirectionValuesInterface {
133 | [key: string]: number;
134 | left: number;
135 | right: number;
136 | top: number;
137 | bottom: number;
138 | }
139 |
140 | interface DrawerReverseDirectionInterface {
141 | [key: string]: string;
142 | left: string;
143 | right: string;
144 | }
145 |
146 | interface SwipeMoveInterface {
147 | value: Point;
148 | direction: string;
149 | }
150 |
151 | class RNNDrawer {
152 | /**
153 | * Generates the drawer component to
154 | * be used with react-native-navigation
155 | *
156 | * @param component
157 | */
158 | static create(Component: React.ComponentType): any {
159 | class WrappedDrawer extends React.Component {
160 | private readonly screenWidth: number;
161 | private readonly screenHeight: number;
162 | private readonly drawerWidth: number;
163 | private readonly drawerHeight: number;
164 | private readonly drawerOpenedValues: DrawerDirectionValuesInterface;
165 | private readonly initialValues: DrawerDirectionValuesInterface;
166 | private panResponder: PanResponderInstance;
167 | private animatedDrawer!: Animated.CompositeAnimation;
168 | private animatedOpacity!: Animated.CompositeAnimation;
169 | private unsubscribeSwipeStart!: () => void;
170 | private unsubscribeSwipeMove!: () => void;
171 | private unsubscribeSwipeEnd!: () => void;
172 | private unsubscribeDismissDrawer!: () => void;
173 | private panningStartedPoint: Point = { moveX: 0, moveY: 0 };
174 | private startedFromSideMenu: boolean = false;
175 | private orientationChangeListener?: EmitterSubscription;
176 |
177 | static defaultProps = {
178 | animationOpenTime: 300,
179 | animationCloseTime: 300,
180 | direction: 'left',
181 | dismissWhenTouchOutside: true,
182 | fadeOpacity: 0.6,
183 | drawerScreenWidth: '80%',
184 | drawerScreenWidthOnLandscape: '30%',
185 | drawerScreenHeight: '100%',
186 | animateDrawerExpanding: true,
187 | disableDragging: false,
188 | disableSwiping: false,
189 | };
190 |
191 | /**
192 | * [ Built-in React method. ]
193 | *
194 | * Setup the component. Executes when the component is created
195 | *
196 | * @param {object} props
197 | */
198 | constructor(props: IProps) {
199 | super(props);
200 |
201 | this.screenWidth = Dimensions.get('window').width;
202 | this.screenHeight = Dimensions.get('window').height;
203 |
204 | this.panResponder = PanResponder.create({
205 | onStartShouldSetPanResponder: (
206 | _evt: GestureResponderEvent,
207 | _gestureState: PanResponderGestureState,
208 | ) => false,
209 | onStartShouldSetPanResponderCapture: (
210 | _evt: GestureResponderEvent,
211 | _gestureState: PanResponderGestureState,
212 | ) => false,
213 | onMoveShouldSetPanResponder: (
214 | _evt: GestureResponderEvent,
215 | _gestureState: PanResponderGestureState,
216 | ) => {
217 | const { dx, dy } = _gestureState;
218 |
219 | if (
220 | this.props.direction === DirectionType.left ||
221 | this.props.direction === DirectionType.right
222 | )
223 | return Math.abs(dx) > 5;
224 | else return Math.abs(dy) > 5;
225 | },
226 | onMoveShouldSetPanResponderCapture: (
227 | _evt: GestureResponderEvent,
228 | _gestureState: PanResponderGestureState,
229 | ) => false,
230 | onPanResponderGrant: (
231 | _evt: GestureResponderEvent,
232 | _gestureState: PanResponderGestureState,
233 | ) => {
234 | const { moveX, moveY } = _gestureState;
235 |
236 | dispatch('SWIPE_START', { moveX, moveY });
237 | },
238 | onPanResponderRelease: (
239 | _evt: GestureResponderEvent,
240 | gestureState: PanResponderGestureState,
241 | ) => {
242 | const { vx } = gestureState;
243 |
244 | // Emit this event when the gesture ends
245 | dispatch('SWIPE_END', vx > 0 ? 'right' : 'left');
246 | },
247 | onPanResponderTerminationRequest: (
248 | _evt: GestureResponderEvent,
249 | _gestureState: PanResponderGestureState,
250 | ) => false,
251 | onShouldBlockNativeResponder: (
252 | _evt: GestureResponderEvent,
253 | _gestureState: PanResponderGestureState,
254 | ) => false,
255 | onPanResponderMove: (
256 | _evt: GestureResponderEvent,
257 | _gestureState: PanResponderGestureState,
258 | ) => {
259 | const { moveX, moveY } = _gestureState;
260 | const direction = this.props.direction || 'left';
261 |
262 | dispatch('SWIPE_MOVE', { value: { moveX, moveY }, direction });
263 | },
264 | });
265 |
266 | /*
267 | * We need to convert the pushed drawer width
268 | * to a number as it can either be a string ('20%')
269 | * or number (400).
270 | */
271 | const _resolveDrawerSize = (
272 | value: number | string,
273 | max: number,
274 | ): number => {
275 | /*
276 | * If the type is a string '%' then it should be a percentage relative
277 | * to our max size.
278 | */
279 | if (typeof value === 'string') {
280 | const valueAsNumber = parseFloat(value as string) || 100;
281 | const size = max * (valueAsNumber / 100);
282 |
283 | return size;
284 | }
285 |
286 | return value;
287 | };
288 |
289 | /** Component Variables */
290 | this.drawerWidth = _resolveDrawerSize(
291 | this.isLandscape()
292 | ? props.drawerScreenWidthOnLandscape
293 | : props.drawerScreenWidth,
294 | this.screenWidth,
295 | );
296 | this.drawerHeight = _resolveDrawerSize(
297 | props.drawerScreenHeight,
298 | this.screenHeight,
299 | );
300 |
301 | this.drawerOpenedValues = {
302 | left: 0,
303 | right: this.screenWidth - this.drawerWidth,
304 | top: this.drawerHeight - this.screenHeight,
305 | bottom: this.screenHeight - this.drawerHeight,
306 | };
307 |
308 | this.initialValues = {
309 | left: -this.drawerWidth,
310 | right: this.screenWidth,
311 | top: -this.screenHeight,
312 | bottom: this.screenHeight,
313 | };
314 |
315 | /** Component State */
316 | this.state = {
317 | sideMenuOpenValue: new Animated.Value(
318 | this.initialValues[props.direction],
319 | ),
320 | sideMenuOverlayOpacity: new Animated.Value(0),
321 | sideMenuSwipingStarted: false,
322 | sideMenuIsDismissing: false,
323 | screenHeight: this.screenHeight,
324 | };
325 |
326 | /** Component Bindings */
327 | this.touchedOutside = this.touchedOutside.bind(this);
328 | this.dismissDrawerWithAnimation = this.dismissDrawerWithAnimation.bind(
329 | this,
330 | );
331 | this.registerListeners = this.registerListeners.bind(this);
332 | this.removeListeners = this.removeListeners.bind(this);
333 | this.isLandscape = this.isLandscape.bind(this);
334 | Navigation.events().bindComponent(this);
335 | }
336 |
337 | /**
338 | * Check if device is in landscape mode
339 | */
340 | isLandscape() {
341 | const dim = Dimensions.get('window');
342 |
343 | return dim.height <= dim.width;
344 | }
345 |
346 | /**
347 | * [ Built-in React method. ]
348 | *
349 | * Executed when the component is mounted to the screen
350 | */
351 | componentDidMount() {
352 | /** Props */
353 | const { direction, fadeOpacity, animateDrawerExpanding } = this.props;
354 |
355 | if (
356 | typeof animateDrawerExpanding !== 'undefined' &&
357 | !animateDrawerExpanding
358 | )
359 | this.startedFromSideMenu = true;
360 |
361 | // Animate side menu open
362 | this.animatedDrawer = Animated.timing(this.state.sideMenuOpenValue, {
363 | toValue: this.drawerOpenedValues[direction],
364 | duration: this.props.animationOpenTime,
365 | useNativeDriver: true,
366 | });
367 |
368 | // Animate outside side menu opacity
369 | this.animatedOpacity = Animated.timing(
370 | this.state.sideMenuOverlayOpacity,
371 | {
372 | toValue: fadeOpacity,
373 | duration: this.props.animationOpenTime,
374 | useNativeDriver: true,
375 | },
376 | );
377 | }
378 |
379 | /**
380 | * [ react-native-navigation method. ]
381 | *
382 | * Executed when the component is navigated to view.
383 | */
384 | componentDidAppear() {
385 | this.registerListeners();
386 |
387 | // If there has been no Swiping, and this component appears, then just start the open animations
388 | if (
389 | !this.state.sideMenuSwipingStarted &&
390 | this.props.animateDrawerExpanding
391 | ) {
392 | this.animatedDrawer.start();
393 | this.animatedOpacity.start();
394 | }
395 | }
396 |
397 | /**
398 | * [ react-native-navigation method. ]
399 | *
400 | * Executed when the component is navigated away from view.
401 | */
402 | componentDidDisappear() {
403 | this.removeListeners();
404 |
405 | dispatch('DRAWER_CLOSED');
406 | }
407 |
408 | onOrientationChange = ({ window }: any) => {
409 | const screenHeight = window.height;
410 |
411 | this.setState({ screenHeight });
412 |
413 | // Apply correct position if opened from right
414 | if (this.props.direction === 'right') {
415 | // Calculates the position of the drawer from the left side of the screen
416 | const alignedMovementValue = window.width - this.drawerWidth;
417 |
418 | this.state.sideMenuOpenValue.setValue(alignedMovementValue);
419 | }
420 | };
421 |
422 | /**
423 | * Registers all the listenrs for this component
424 | */
425 | registerListeners() {
426 | /** Props */
427 | const { direction, fadeOpacity } = this.props;
428 |
429 | // Adapt the drawer's size on orientation change
430 | this.orientationChangeListener = Dimensions.addEventListener(
431 | 'change',
432 | this.onOrientationChange,
433 | );
434 |
435 | // Executes when the side of the screen interaction starts
436 | this.unsubscribeSwipeStart = listen('SWIPE_START', (value: Point) => {
437 | this.panningStartedPoint.moveX = value.moveX;
438 | this.panningStartedPoint.moveY = value.moveY;
439 |
440 | this.setState({
441 | sideMenuSwipingStarted: true,
442 | });
443 | });
444 |
445 | // Executes when the side of the screen is interacted with
446 | this.unsubscribeSwipeMove = listen(
447 | 'SWIPE_MOVE',
448 | ({ value, direction: swipeDirection }: SwipeMoveInterface) => {
449 | // Cover special case when we are swiping from the edge of the screen
450 | if (this.startedFromSideMenu) {
451 | if (direction === 'left' && value.moveX < this.drawerWidth) {
452 | this.state.sideMenuOpenValue.setValue(
453 | value.moveX - this.drawerWidth,
454 | );
455 | const normalizedOpacity = Math.min(
456 | (value.moveX / this.drawerWidth) * fadeOpacity,
457 | fadeOpacity,
458 | );
459 | this.state.sideMenuOverlayOpacity.setValue(normalizedOpacity);
460 | }
461 | if (
462 | direction === 'right' &&
463 | this.screenWidth - value.moveX < this.drawerWidth
464 | ) {
465 | this.state.sideMenuOpenValue.setValue(value.moveX);
466 | const normalizedOpacity = Math.min(
467 | ((this.screenWidth - value.moveX) / this.drawerWidth) *
468 | fadeOpacity,
469 | fadeOpacity,
470 | );
471 | this.state.sideMenuOverlayOpacity.setValue(normalizedOpacity);
472 | }
473 |
474 | return;
475 | }
476 |
477 | if (this.props.disableDragging) return;
478 | // Calculates the translateX / translateY value
479 | let alignedMovementValue = 0;
480 | // To swap the direction if needed
481 | let directionModifier = 1;
482 | // Whether we use the height of the drawer or the width
483 | let drawerDimension = this.drawerWidth;
484 |
485 | if (swipeDirection === 'left') {
486 | alignedMovementValue =
487 | value.moveX - this.panningStartedPoint.moveX;
488 | } else if (swipeDirection === 'right') {
489 | alignedMovementValue =
490 | this.panningStartedPoint.moveX - value.moveX;
491 | directionModifier = -1;
492 | } else if (swipeDirection === 'bottom') {
493 | alignedMovementValue =
494 | this.panningStartedPoint.moveY - value.moveY;
495 | directionModifier = -1;
496 | drawerDimension = this.drawerHeight;
497 | } else if (swipeDirection === 'top') {
498 | alignedMovementValue =
499 | value.moveY - this.panningStartedPoint.moveY;
500 | drawerDimension = this.drawerHeight;
501 | }
502 |
503 | // Calculates the percentage 0 - 1 of which the drawer is open
504 | const openedPercentage =
505 | Math.abs(drawerDimension + alignedMovementValue) /
506 | drawerDimension;
507 | // Calculates the opacity to set of the screen based on the percentage the drawer is open
508 | const normalizedOpacity = Math.min(
509 | openedPercentage * fadeOpacity,
510 | fadeOpacity,
511 | );
512 |
513 | // Does not allow the drawer to go further than the maximum width / height
514 | if (0 > alignedMovementValue) {
515 | // Sets the animation values, we use this so we can resume animation from any point
516 | this.state.sideMenuOpenValue.setValue(
517 | this.drawerOpenedValues[direction] +
518 | alignedMovementValue * directionModifier,
519 | );
520 | this.state.sideMenuOverlayOpacity.setValue(normalizedOpacity);
521 | }
522 | },
523 | );
524 |
525 | // Executes when the side of the screen interaction ends
526 | this.unsubscribeSwipeEnd = listen(
527 | 'SWIPE_END',
528 | (swipeDirection: string) => {
529 | if (this.props.disableSwiping && !this.startedFromSideMenu) return;
530 |
531 | const reverseDirection: DrawerReverseDirectionInterface = {
532 | right: 'left',
533 | left: 'right',
534 | top: 'bottom',
535 | bottom: 'top',
536 | };
537 | // In case the drawer started by dragging the edge of the screen reset the flag
538 | this.startedFromSideMenu = false;
539 |
540 | if (swipeDirection === reverseDirection[direction]) {
541 | this.animatedDrawer.start();
542 | this.animatedOpacity.start();
543 | } else {
544 | if (!this.state.sideMenuIsDismissing) {
545 | this.setState(
546 | {
547 | sideMenuIsDismissing: true,
548 | },
549 | () => {
550 | this.dismissDrawerWithAnimation();
551 | },
552 | );
553 | }
554 | }
555 | },
556 | );
557 |
558 | // Executes when the drawer needs to be dismissed
559 | this.unsubscribeDismissDrawer = listen('DISMISS_DRAWER', () => {
560 | if (!this.state.sideMenuIsDismissing) {
561 | this.dismissDrawerWithAnimation();
562 | }
563 | });
564 | }
565 |
566 | /**
567 | * Removes all the listenrs from this component
568 | */
569 | removeListeners() {
570 | if (this.orientationChangeListener)
571 | this.orientationChangeListener.remove();
572 | if (this.unsubscribeSwipeStart) this.unsubscribeSwipeStart();
573 | if (this.unsubscribeSwipeMove) this.unsubscribeSwipeMove();
574 | if (this.unsubscribeSwipeEnd) this.unsubscribeSwipeEnd();
575 | if (this.unsubscribeDismissDrawer) this.unsubscribeDismissDrawer();
576 | }
577 |
578 | /**
579 | * [ Built-in React method. ]
580 | *
581 | * Allows us to render JSX to the screen
582 | */
583 | render() {
584 | /** Styles */
585 | const { sideMenuOverlayStyle, sideMenuContainerStyle } = styles;
586 | /** Props */
587 | const { direction, style } = this.props;
588 | /** State */
589 | const { sideMenuOpenValue, sideMenuOverlayOpacity } = this.state;
590 | /** Variables */
591 | const animatedValue =
592 | direction === DirectionType.left || direction === DirectionType.right
593 | ? { translateX: sideMenuOpenValue }
594 | : { translateY: sideMenuOpenValue };
595 |
596 | return (
597 |
601 |
602 |
608 |
609 |
620 |
621 |
622 |
623 | );
624 | }
625 |
626 | /**
627 | * Touched outside drawer
628 | */
629 | touchedOutside() {
630 | const { dismissWhenTouchOutside } = this.props;
631 |
632 | if (dismissWhenTouchOutside) {
633 | this.dismissDrawerWithAnimation();
634 | }
635 | }
636 |
637 | /**
638 | * Dismisses drawer with animation
639 | */
640 | dismissDrawerWithAnimation() {
641 | const { direction } = this.props;
642 | const { sideMenuIsDismissing } = this.state;
643 | const closeValues: DrawerDirectionValuesInterface = {
644 | left: -this.drawerWidth,
645 | right: this.screenWidth,
646 | top: -this.screenHeight,
647 | bottom: this.screenHeight,
648 | };
649 |
650 | // Animate side menu close
651 | Animated.timing(this.state.sideMenuOpenValue, {
652 | toValue: closeValues[direction],
653 | duration: this.props.animationCloseTime,
654 | useNativeDriver: true,
655 | }).start(() => {
656 | Navigation.dismissOverlay(this.props.componentId);
657 | this.setState({ sideMenuIsDismissing: false });
658 | });
659 |
660 | // Animate outside side menu opacity
661 | Animated.timing(this.state.sideMenuOverlayOpacity, {
662 | toValue: 0,
663 | duration: this.props.animationCloseTime,
664 | useNativeDriver: true,
665 | }).start();
666 | }
667 | }
668 |
669 | return WrappedDrawer;
670 | }
671 |
672 | /**
673 | * Shows a drawer component
674 | *
675 | * @param layout
676 | */
677 | static showDrawer(layout: Layout) {
678 | // By default for this library, we make the 'componentBackgroundColor' transparent
679 | const componentBackgroundColor =
680 | layout?.component?.options?.layout?.componentBackgroundColor ??
681 | 'transparent';
682 | const options = {
683 | ...layout?.component?.options,
684 | layout: {
685 | componentBackgroundColor: componentBackgroundColor,
686 | },
687 | };
688 |
689 | // Mutate options to add 'transparent' by default
690 | // @ts-ignore
691 | layout.component.options = { ...options };
692 |
693 | Navigation.showOverlay(layout);
694 | }
695 |
696 | /**
697 | * Dismiss the drawer component
698 | */
699 | static dismissDrawer() {
700 | dispatch('DISMISS_DRAWER', true);
701 | }
702 | }
703 |
704 | export default RNNDrawer;
705 |
706 | /** -------------------------------------------- */
707 | /** Component Styling */
708 | /** -------------------------------------------- */
709 | const styles = StyleSheet.create({
710 | sideMenuContainerStyle: {
711 | flex: 1,
712 | flexDirection: 'row',
713 | },
714 | sideMenuOverlayStyle: {
715 | position: 'absolute',
716 | width: '100%',
717 | height: '100%',
718 | backgroundColor: '#000',
719 | },
720 | });
721 |
--------------------------------------------------------------------------------
/src/SideMenuView.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Luke Brandon Farrell
3 | * @title SideMenuView.js
4 | * @description A swipeable view to open a drawer.
5 | */
6 |
7 | /* NPM - Node Package Manage */
8 | import * as React from 'react';
9 | import {
10 | View,
11 | PanResponder,
12 | Dimensions,
13 | PanResponderCallbacks,
14 | PanResponderInstance,
15 | GestureResponderEvent,
16 | PanResponderGestureState,
17 | StyleProp,
18 | ViewStyle,
19 | } from 'react-native';
20 | import { Options } from 'react-native-navigation';
21 | /* Utils - Project Utilities */
22 | import RNNDrawer from './RNNDrawer';
23 | import { listen, dispatch } from './events';
24 | import { DirectionType } from './RNNDrawer';
25 |
26 | const screenHeight: number = Dimensions.get('screen').height;
27 |
28 | interface IProps {
29 | swipeSensitivity?: number;
30 | sideMargin?: number;
31 | sideMarginLeft?: number;
32 | sideMarginRight?: number;
33 | style?: StyleProp;
34 | drawerName: string;
35 | direction: 'left' | 'right';
36 | passProps?: any;
37 | options?: Options;
38 | }
39 |
40 | class SideMenuView extends React.Component {
41 | private isOpened: boolean;
42 | private _panResponderMethods: PanResponderCallbacks;
43 | private _leftPanResponder: PanResponderInstance;
44 | private _rightPanResponder: PanResponderInstance;
45 | private unsubscribeDrawerClosed: any;
46 |
47 | static defaultProps = {
48 | sideMargin: 15,
49 | swipeSensitivity: 0.2,
50 | direction: 'left',
51 | };
52 |
53 | /**
54 | * [ Built-in React method. ]
55 | *
56 | * Setup the component. Executes when the component is created
57 | *
58 | * @param {object} props
59 | */
60 | constructor(props: IProps) {
61 | super(props);
62 |
63 | this.isOpened = false;
64 |
65 | const {
66 | swipeSensitivity,
67 | drawerName,
68 | direction,
69 | passProps,
70 | options,
71 | } = props;
72 | const directionIsLeft = direction ? direction == 'left' : true;
73 | this._panResponderMethods = {
74 | // Ask to be the responder:
75 | onStartShouldSetPanResponder: (
76 | _evt: GestureResponderEvent,
77 | _gestureState: PanResponderGestureState,
78 | ) => true,
79 | onStartShouldSetPanResponderCapture: (
80 | _evt: GestureResponderEvent,
81 | _gestureState: PanResponderGestureState,
82 | ) => true,
83 | onMoveShouldSetPanResponder: (
84 | _evt: GestureResponderEvent,
85 | _gestureState: PanResponderGestureState,
86 | ) => true,
87 | onMoveShouldSetPanResponderCapture: (
88 | _evt: GestureResponderEvent,
89 | _gestureState: PanResponderGestureState,
90 | ) => true,
91 | onPanResponderGrant: (
92 | _evt: GestureResponderEvent,
93 | _gestureState: PanResponderGestureState,
94 | ) => {
95 | dispatch('SWIPE_START');
96 | },
97 | onPanResponderRelease: (
98 | _evt: GestureResponderEvent,
99 | gestureState: PanResponderGestureState,
100 | ) => {
101 | const { vx } = gestureState;
102 |
103 | // Emit this event when the gesture ends
104 | dispatch('SWIPE_END', vx > 0 ? 'right' : 'left');
105 | },
106 | onPanResponderTerminationRequest: (
107 | _evt: GestureResponderEvent,
108 | _gestureState: PanResponderGestureState,
109 | ) => false,
110 | onShouldBlockNativeResponder: (
111 | _evt: GestureResponderEvent,
112 | _gestureState: PanResponderGestureState,
113 | ) => false,
114 | };
115 |
116 | // LEFT PAN RESPONDER
117 | this._leftPanResponder = PanResponder.create({
118 | ...this._panResponderMethods,
119 | onPanResponderMove: (
120 | _evt: GestureResponderEvent,
121 | gestureState: PanResponderGestureState,
122 | ) => {
123 | const { moveX, vx } = gestureState;
124 |
125 | // Emit this event on movement
126 | dispatch('SWIPE_MOVE', { value: { moveX }, direction: 'left' });
127 |
128 | // Left Swipe
129 | if (typeof swipeSensitivity !== 'undefined') {
130 | if (vx > swipeSensitivity && !this.isOpened && directionIsLeft) {
131 | this.isOpened = true;
132 | RNNDrawer.showDrawer({
133 | component: {
134 | name: drawerName,
135 | passProps: {
136 | direction: DirectionType.left,
137 | parentComponentId: passProps?.parentComponentId,
138 | animateDrawerExpanding: false,
139 | ...passProps,
140 | },
141 | options: { ...options },
142 | },
143 | });
144 | }
145 | }
146 | },
147 | });
148 |
149 | // RIGHT PAN RESPONDER
150 | this._rightPanResponder = PanResponder.create({
151 | ...this._panResponderMethods,
152 | onPanResponderMove: (
153 | _evt: GestureResponderEvent,
154 | gestureState: PanResponderGestureState,
155 | ) => {
156 | const { moveX, vx } = gestureState;
157 |
158 | // Emit this event on movement
159 | dispatch('SWIPE_MOVE', { value: { moveX }, direction: 'right' });
160 |
161 | // Right Swipe
162 | if (typeof swipeSensitivity !== 'undefined') {
163 | if (vx > -swipeSensitivity && !this.isOpened && !directionIsLeft) {
164 | this.isOpened = true;
165 | RNNDrawer.showDrawer({
166 | component: {
167 | name: drawerName,
168 | passProps: {
169 | direction: DirectionType.right,
170 | parentComponentId: passProps?.parentComponentId,
171 | animateDrawerExpanding: false,
172 | ...passProps,
173 | },
174 | options: { ...options },
175 | },
176 | });
177 | }
178 | }
179 | },
180 | });
181 |
182 | this.registerListeners = this.registerListeners.bind(this);
183 | this.removeListeners = this.removeListeners.bind(this);
184 | }
185 |
186 | /**
187 | * [ Built-in React method. ]
188 | *
189 | * Executed when the component is mounted to the screen
190 | */
191 | componentDidMount() {
192 | this.registerListeners();
193 | }
194 |
195 | /**
196 | * Registers all the listenrs for this component
197 | */
198 | registerListeners() {
199 | // Event fires when drawer is closed
200 | this.unsubscribeDrawerClosed = listen('DRAWER_CLOSED', () => {
201 | this.isOpened = false;
202 | });
203 | }
204 |
205 | /**
206 | * Removes all the listenrs from this component
207 | */
208 | removeListeners() {
209 | this.unsubscribeDrawerClosed();
210 | }
211 |
212 | /**
213 | * [ Built-in React method. ]
214 | *
215 | * Allows us to render JSX to the screen
216 | */
217 | render() {
218 | /** Props */
219 | const {
220 | children,
221 | direction,
222 | sideMargin,
223 | sideMarginLeft,
224 | sideMarginRight,
225 | ...props
226 | } = this.props;
227 |
228 | const directionIsLeft = direction ? direction == 'left' : true;
229 | return (
230 |
231 | {children}
232 |
233 | {directionIsLeft ? (
234 |
244 | ) : (
245 |
255 | )}
256 |
257 | );
258 | }
259 | }
260 |
261 | export default SideMenuView;
262 |
--------------------------------------------------------------------------------
/src/events.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Luke Brandon Farrell
3 | * @description Event dispatcher for comunication between components.
4 | */
5 |
6 | interface EvnetsInterface {
7 | [key: string]: any;
8 | }
9 |
10 | /**
11 | * @description events
12 | * @private
13 | */
14 | var _events: EvnetsInterface = {};
15 |
16 | /**
17 | * @description add listener
18 | * @public
19 | * @param {string} name name listener
20 | * @param {function} func function for call
21 | * @returns {function} unsubscribe function
22 | */
23 | export function listen(name: string, func: any): () => void {
24 | if (!_events[name]) _events[name] = { count: 0, funcs: {} };
25 |
26 | const key = _events[name].count++;
27 | _events[name].funcs[key] = func;
28 |
29 | return function () {
30 | delete _events[name].funcs[key];
31 | };
32 | }
33 |
34 | /**
35 | * @description dispatch to listener
36 | * @public
37 | * @param {string} name name listener
38 | * @param {any} arg argument for send to listen(...)
39 | * @returns {void}
40 | */
41 | export function dispatch(name: string, arg?: any): void {
42 | if (_events[name])
43 | for (var func in _events[name].funcs)
44 | _events[name].funcs[func] && _events[name].funcs[func](arg);
45 | }
46 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { default as RNNDrawer } from './RNNDrawer';
2 | export { default as SideMenuView } from './SideMenuView';
3 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "declaration": true,
6 | "outDir": "./lib",
7 | "strict": true,
8 | "jsx": "react",
9 | "skipLibCheck": true,
10 | },
11 | "include": ["src"],
12 | "exclude": ["node_modules", "**/__tests__/*"]
13 | }
--------------------------------------------------------------------------------