├── Example ├── .watchmanconfig ├── .gitattributes ├── .babelrc ├── app.json ├── android │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── values │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ └── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── assets │ │ │ │ └── fonts │ │ │ │ │ ├── Entypo.ttf │ │ │ │ │ ├── Zocial.ttf │ │ │ │ │ ├── Feather.ttf │ │ │ │ │ ├── Ionicons.ttf │ │ │ │ │ ├── Octicons.ttf │ │ │ │ │ ├── EvilIcons.ttf │ │ │ │ │ ├── FontAwesome.ttf │ │ │ │ │ ├── Foundation.ttf │ │ │ │ │ ├── MaterialIcons.ttf │ │ │ │ │ ├── SimpleLineIcons.ttf │ │ │ │ │ └── MaterialCommunityIcons.ttf │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ │ └── AndroidManifest.xml │ │ ├── BUCK │ │ ├── proguard-rules.pro │ │ └── build.gradle │ ├── keystores │ │ ├── debug.keystore.properties │ │ └── BUCK │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── build.gradle │ ├── gradle.properties │ ├── gradlew.bat │ └── gradlew ├── .buckconfig ├── index.ios.js ├── index.android.js ├── __tests__ │ ├── index.ios.js │ └── index.android.js ├── SimpleExample.js ├── ios │ ├── Example │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── ExampleTests │ │ ├── Info.plist │ │ └── ExampleTests.m │ ├── Example-tvOSTests │ │ └── Info.plist │ ├── Example-tvOS │ │ └── Info.plist │ └── Example.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ ├── Example.xcscheme │ │ └── Example-tvOS.xcscheme ├── ScrollableTabsExample.js ├── package.json ├── .gitignore ├── .flowconfig ├── OverlayExample.js ├── FacebookExample.js ├── DynamicExample.js ├── FacebookTabBar.js └── index.js ├── .npmignore ├── .gitignore ├── Button.ios.js ├── StaticContainer.js ├── Button.android.js ├── SceneComponent.js ├── .github └── ISSUE_TEMPLATE.md ├── package.json ├── DefaultTabBar.js ├── README.md ├── .eslintrc ├── ScrollableTabBar.js ├── index.js └── yarn.lock /Example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | Example 2 | .github/ -------------------------------------------------------------------------------- /Example/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /Example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } 4 | -------------------------------------------------------------------------------- /Example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Example", 3 | "displayName": "Example" 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | npm-debug.log 3 | node_modules/ 4 | .idea/ 5 | .reploy 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /Example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Example 3 | 4 | -------------------------------------------------------------------------------- /Example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /Example/android/keystores/debug.keystore.properties: -------------------------------------------------------------------------------- 1 | key.store=debug.keystore 2 | key.alias=androiddebugkey 3 | key.store.password=android 4 | key.alias.password=android 5 | -------------------------------------------------------------------------------- /Example/index.ios.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry, } from 'react-native'; 2 | import Example from './index.js'; 3 | 4 | AppRegistry.registerComponent('Example', () => Example); 5 | -------------------------------------------------------------------------------- /Example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Example/index.android.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry, } from 'react-native'; 2 | import Example from './index.js'; 3 | 4 | AppRegistry.registerComponent('Example', () => Example); 5 | -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/Entypo.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/Zocial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/Zocial.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/Feather.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/Feather.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/Octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/Octicons.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/EvilIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/EvilIcons.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/Foundation.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /Example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Example/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptomasroos/react-native-scrollable-tab-view/HEAD/Example/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /Example/android/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = "debug", 3 | properties = "debug.keystore.properties", 4 | store = "debug.keystore", 5 | visibility = [ 6 | "PUBLIC", 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /Example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Example' 2 | include ':react-native-vector-icons' 3 | project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') 4 | 5 | include ':app' 6 | -------------------------------------------------------------------------------- /Example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 6 | -------------------------------------------------------------------------------- /Button.ios.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactNative = require('react-native'); 3 | const { 4 | TouchableOpacity, 5 | View, 6 | } = ReactNative; 7 | 8 | const Button = (props) => { 9 | return 10 | {props.children} 11 | ; 12 | }; 13 | 14 | module.exports = Button; 15 | -------------------------------------------------------------------------------- /Example/__tests__/index.ios.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.ios.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /Example/__tests__/index.android.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.android.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /Example/android/app/src/main/java/com/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "Example"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /StaticContainer.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | 3 | class StaticContainer extends React.Component { 4 | 5 | shouldComponentUpdate(nextProps: Object): boolean { 6 | return !!nextProps.shouldUpdate; 7 | } 8 | 9 | render(): ?ReactElement { 10 | var child = this.props.children; 11 | if (child === null || child === false) { 12 | return null; 13 | } 14 | return React.Children.only(child); 15 | } 16 | 17 | } 18 | 19 | module.exports = StaticContainer; 20 | -------------------------------------------------------------------------------- /Button.android.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactNative = require('react-native'); 3 | const { 4 | TouchableNativeFeedback, 5 | View, 6 | } = ReactNative; 7 | 8 | const Button = (props) => { 9 | return 14 | {props.children} 15 | ; 16 | }; 17 | 18 | module.exports = Button; 19 | -------------------------------------------------------------------------------- /Example/SimpleExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Text, 4 | } from 'react-native'; 5 | 6 | import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view'; 7 | 8 | export default () => { 9 | return } 13 | > 14 | My 15 | favorite 16 | project 17 | ; 18 | } 19 | -------------------------------------------------------------------------------- /Example/ios/Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SceneComponent.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactNative = require('react-native'); 3 | const { Component } = React; 4 | const { View, StyleSheet } = ReactNative; 5 | 6 | const StaticContainer = require('./StaticContainer'); 7 | 8 | const SceneComponent = (Props) => { 9 | const { shouldUpdated, ...props } = Props; 10 | return 11 | 12 | {props.children} 13 | 14 | ; 15 | }; 16 | 17 | module.exports = SceneComponent; 18 | -------------------------------------------------------------------------------- /Example/ios/Example/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Example/ScrollableTabsExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Text, 4 | View, 5 | } from 'react-native'; 6 | 7 | import ScrollableTabView, { ScrollableTabBar } from 'react-native-scrollable-tab-view'; 8 | 9 | export default () => { 10 | return } 14 | > 15 | My 16 | favorite 17 | project 18 | favorite 19 | project 20 | ; 21 | } 22 | -------------------------------------------------------------------------------- /Example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest" 8 | }, 9 | "dependencies": { 10 | "create-react-class": "^15.6.2", 11 | "react": "16.0.0", 12 | "react-native": "0.48.4", 13 | "react-native-scrollable-tab-view": "file:../", 14 | "react-native-vector-icons": "^4.4.0", 15 | "react-navigation": "^1.0.0-beta.13" 16 | }, 17 | "devDependencies": { 18 | "babel-jest": "21.2.0", 19 | "babel-preset-react-native": "4.0.0", 20 | "jest": "21.2.1", 21 | "react-test-renderer": "16.0.0" 22 | }, 23 | "jest": { 24 | "preset": "react-native" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /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 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$rootDir/../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Example/ios/Example/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/ExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 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/Example-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 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/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 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /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://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 50 | 51 | fastlane/report.xml 52 | fastlane/Preview.html 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 9 | 10 | - [ ] I have searched [existing issues](https://github.com/happypancake/react-native-scrollable-tab-view/issues) 11 | - [ ] I am using the [latest scrollable tab view version](https://www.npmjs.com/package/react-native-scrollable-tab-view) 12 | 13 | 16 | 17 | ## Steps to Reproduce 18 | 21 | 22 | ## Expected Behavior 23 | 26 | 27 | ## Actual Behavior 28 | 31 | -------------------------------------------------------------------------------- /Example/android/app/src/main/java/com/example/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import android.app.Application; 4 | 5 | import com.facebook.react.ReactApplication; 6 | import com.oblador.vectoricons.VectorIconsPackage; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.shell.MainReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class MainApplication extends Application implements ReactApplication { 16 | 17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | return Arrays.asList( 26 | new MainReactPackage(), 27 | new VectorIconsPackage() 28 | ); 29 | } 30 | }; 31 | 32 | @Override 33 | public ReactNativeHost getReactNativeHost() { 34 | return mReactNativeHost; 35 | } 36 | 37 | @Override 38 | public void onCreate() { 39 | super.onCreate(); 40 | SoLoader.init(this, /* native exopackage */ false); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-scrollable-tab-view", 3 | "version": "1.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "eslint -c .eslintrc . --ignore-path .gitignore", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/brentvatne/react-native-scrollable-tab-view.git" 13 | }, 14 | "keywords": [ 15 | "react-native-component", 16 | "react-component", 17 | "react-native", 18 | "ios", 19 | "tab", 20 | "scrollable" 21 | ], 22 | "author": "Brent Vatne", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/brentvatne/react-native-scrollable-tab-view/issues" 26 | }, 27 | "peerDependencies": { 28 | "react-native": ">=0.20.0" 29 | }, 30 | "homepage": "https://github.com/brentvatne/react-native-scrollable-tab-view#readme", 31 | "dependencies": { 32 | "@react-native-community/viewpager": "3.3.0", 33 | "create-react-class": "^15.6.2", 34 | "deprecated-react-native-prop-types": "^2.3.0", 35 | "prop-types": "^15.6.0", 36 | "react-timer-mixin": "^0.13.3" 37 | }, 38 | "devDependencies": { 39 | "babel-eslint": "^6.1.2", 40 | "eslint": "^3.1.1" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example/ios/Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import 13 | #import 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | NSURL *jsCodeLocation; 20 | 21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 22 | 23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 24 | moduleName:@"Example" 25 | initialProperties:nil 26 | launchOptions:launchOptions]; 27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 28 | 29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 30 | UIViewController *rootViewController = [UIViewController new]; 31 | rootViewController.view = rootView; 32 | self.window.rootViewController = rootViewController; 33 | [self.window makeKeyAndVisible]; 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/Libraries/react-native/react-native-interface.js 21 | node_modules/react-native/flow 22 | flow/ 23 | 24 | [options] 25 | emoji=true 26 | 27 | module.system=haste 28 | 29 | munge_underscores=true 30 | 31 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 32 | 33 | suppress_type=$FlowIssue 34 | suppress_type=$FlowFixMe 35 | suppress_type=$FixMe 36 | 37 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 38 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 40 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 41 | 42 | unsafe.enable_getters_and_setters=true 43 | 44 | [version] 45 | ^0.49.1 46 | -------------------------------------------------------------------------------- /Example/OverlayExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | ScrollView, 5 | } from 'react-native'; 6 | 7 | import ScrollableTabView, { DefaultTabBar, } from 'react-native-scrollable-tab-view'; 8 | import Icon from 'react-native-vector-icons/Ionicons'; 9 | 10 | // Using tabBarPosition='overlayTop' or 'overlayBottom' lets the content show through a 11 | // semitransparent tab bar. Note that if you build a custom tab bar component, its outer container 12 | // must consume a 'style' prop (e.g. { 14 | return } 17 | tabBarPosition='overlayTop' 18 | > 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ; 31 | } 32 | 33 | const styles = StyleSheet.create({ 34 | container: { 35 | marginTop: 30, 36 | }, 37 | icon: { 38 | width: 300, 39 | height: 300, 40 | alignSelf: 'center', 41 | }, 42 | }); 43 | -------------------------------------------------------------------------------- /Example/ios/Example-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 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 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | NSAppTransportSecurity 42 | 43 | 44 | NSExceptionDomains 45 | 46 | localhost 47 | 48 | NSExceptionAllowsInsecureHTTPLoads 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /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 | lib_deps = [] 12 | 13 | for jarfile in glob(['libs/*.jar']): 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 | 21 | for aarfile in glob(['libs/*.aar']): 22 | name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')] 23 | lib_deps.append(':' + name) 24 | android_prebuilt_aar( 25 | name = name, 26 | aar = aarfile, 27 | ) 28 | 29 | android_library( 30 | name = "all-libs", 31 | exported_deps = lib_deps, 32 | ) 33 | 34 | android_library( 35 | name = "app-code", 36 | srcs = glob([ 37 | "src/main/java/**/*.java", 38 | ]), 39 | deps = [ 40 | ":all-libs", 41 | ":build_config", 42 | ":res", 43 | ], 44 | ) 45 | 46 | android_build_config( 47 | name = "build_config", 48 | package = "com.example", 49 | ) 50 | 51 | android_resource( 52 | name = "res", 53 | package = "com.example", 54 | res = "src/main/res", 55 | ) 56 | 57 | android_binary( 58 | name = "app", 59 | keystore = "//android/keystores:debug", 60 | manifest = "src/main/AndroidManifest.xml", 61 | package_type = "debug", 62 | deps = [ 63 | ":app-code", 64 | ], 65 | ) 66 | -------------------------------------------------------------------------------- /Example/FacebookExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | ScrollView, 7 | } from 'react-native'; 8 | 9 | import FacebookTabBar from './FacebookTabBar'; 10 | import ScrollableTabView from 'react-native-scrollable-tab-view'; 11 | 12 | export default () => { 13 | return } 17 | > 18 | 19 | 20 | News 21 | 22 | 23 | 24 | 25 | Friends 26 | 27 | 28 | 29 | 30 | Messenger 31 | 32 | 33 | 34 | 35 | Notifications 36 | 37 | 38 | 39 | 40 | Other nav 41 | 42 | 43 | ; 44 | } 45 | 46 | const styles = StyleSheet.create({ 47 | tabView: { 48 | flex: 1, 49 | padding: 10, 50 | backgroundColor: 'rgba(0,0,0,0.01)', 51 | }, 52 | card: { 53 | borderWidth: 1, 54 | backgroundColor: '#fff', 55 | borderColor: 'rgba(0,0,0,0.1)', 56 | margin: 5, 57 | height: 150, 58 | padding: 15, 59 | shadowColor: '#ccc', 60 | shadowOffset: { width: 2, height: 2, }, 61 | shadowOpacity: 0.5, 62 | shadowRadius: 3, 63 | }, 64 | }); 65 | -------------------------------------------------------------------------------- /Example/DynamicExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Text, 4 | TouchableHighlight, 5 | } from 'react-native'; 6 | import TimerMixin from 'react-timer-mixin'; 7 | import ScrollableTabView, { ScrollableTabBar, } from 'react-native-scrollable-tab-view'; 8 | import createReactClass from 'create-react-class'; 9 | 10 | const Child = createReactClass({ 11 | onEnter() { 12 | console.log('enter: ' + this.props.i); // eslint-disable-line no-console 13 | }, 14 | 15 | onLeave() { 16 | console.log('leave: ' + this.props.i); // eslint-disable-line no-console 17 | }, 18 | 19 | render() { 20 | const i = this.props.i; 21 | return {`tab${i}`}; 22 | }, 23 | }); 24 | 25 | export default createReactClass({ 26 | mixins: [TimerMixin, ], 27 | children: [], 28 | 29 | getInitialState() { 30 | return { 31 | tabs: [1, 2], 32 | }; 33 | }, 34 | 35 | componentDidMount() { 36 | this.setTimeout( 37 | () => { this.setState({ tabs: [1, 2, 3, 4, 5, 6, ], }); }, 38 | 100 39 | ); 40 | }, 41 | 42 | handleChangeTab({i, ref, from, }) { 43 | this.children[i].onEnter(); 44 | this.children[from].onLeave(); 45 | }, 46 | 47 | renderTab(name, page, isTabActive, onPressHandler, onLayoutHandler) { 48 | return onPressHandler(page)} 51 | onLayout={onLayoutHandler} 52 | style={{flex: 1, width: 100, }} 53 | underlayColor="#aaaaaa" 54 | > 55 | {name} 56 | ; 57 | }, 58 | 59 | render() { 60 | return } 63 | onChangeTab={this.handleChangeTab} 64 | > 65 | {this.state.tabs.map((tab, i) => { 66 | return (this.children[i] = ref)} 68 | tabLabel={`tab${i}`} 69 | i={i} 70 | key={i} 71 | />; 72 | })} 73 | ; 74 | }, 75 | }); 76 | -------------------------------------------------------------------------------- /Example/FacebookTabBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | TouchableOpacity, 7 | } from 'react-native'; 8 | import Icon from 'react-native-vector-icons/Ionicons'; 9 | 10 | class FacebookTabBar extends React.Component { 11 | icons = []; 12 | 13 | constructor(props) { 14 | super(props); 15 | this.icons = []; 16 | } 17 | 18 | componentDidMount() { 19 | this._listener = this.props.scrollValue.addListener(this.setAnimationValue.bind(this)); 20 | } 21 | 22 | setAnimationValue({ value, }) { 23 | this.icons.forEach((icon, i) => { 24 | const progress = (value - i >= 0 && value - i <= 1) ? value - i : 1; 25 | icon.setNativeProps({ 26 | style: { 27 | color: this.iconColor(progress), 28 | }, 29 | }); 30 | }); 31 | } 32 | 33 | //color between rgb(59,89,152) and rgb(204,204,204) 34 | iconColor(progress) { 35 | const red = 59 + (204 - 59) * progress; 36 | const green = 89 + (204 - 89) * progress; 37 | const blue = 152 + (204 - 152) * progress; 38 | return `rgb(${red}, ${green}, ${blue})`; 39 | } 40 | 41 | render() { 42 | return 43 | {this.props.tabs.map((tab, i) => { 44 | return this.props.goToPage(i)} style={styles.tab}> 45 | { this.icons[i] = icon; }} 50 | /> 51 | ; 52 | })} 53 | ; 54 | } 55 | } 56 | 57 | const styles = StyleSheet.create({ 58 | tab: { 59 | flex: 1, 60 | alignItems: 'center', 61 | justifyContent: 'center', 62 | paddingBottom: 10, 63 | }, 64 | tabs: { 65 | height: 45, 66 | flexDirection: 'row', 67 | paddingTop: 5, 68 | borderWidth: 1, 69 | borderTopWidth: 0, 70 | borderLeftWidth: 0, 71 | borderRightWidth: 0, 72 | borderBottomColor: 'rgba(0,0,0,0.05)', 73 | }, 74 | }); 75 | 76 | export default FacebookTabBar; 77 | -------------------------------------------------------------------------------- /Example/ios/Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 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 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | NSLocationWhenInUseUsageDescription 42 | 43 | NSAppTransportSecurity 44 | 45 | NSExceptionDomains 46 | 47 | localhost 48 | 49 | NSExceptionAllowsInsecureHTTPLoads 50 | 51 | 52 | 53 | 54 | UIAppFonts 55 | 56 | Entypo.ttf 57 | EvilIcons.ttf 58 | Feather.ttf 59 | FontAwesome.ttf 60 | Foundation.ttf 61 | Ionicons.ttf 62 | MaterialCommunityIcons.ttf 63 | MaterialIcons.ttf 64 | Octicons.ttf 65 | SimpleLineIcons.ttf 66 | Zocial.ttf 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Example/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | ScrollView, 7 | TouchableOpacity, 8 | } from 'react-native'; 9 | import createReactClass from 'create-react-class'; 10 | import { StackNavigator } from 'react-navigation'; 11 | import SimpleExample from './SimpleExample'; 12 | import ScrollableTabsExample from './ScrollableTabsExample'; 13 | import OverlayExample from './OverlayExample'; 14 | import FacebookExample from './FacebookExample'; 15 | import DynamicExample from './DynamicExample'; 16 | 17 | const HomeScreen = createReactClass({ 18 | navigationOptions: { 19 | title: 'Welcome', 20 | }, 21 | 22 | render() { 23 | const { navigate } = this.props.navigation; 24 | 25 | return 26 | navigate('Simple')} 29 | > 30 | Simple example 31 | 32 | 33 | navigate('Scrollable')} 36 | > 37 | Scrollable tabs example 38 | 39 | 40 | navigate('Overlay')} 43 | > 44 | Overlay example 45 | 46 | 47 | navigate('Facebook')} 50 | > 51 | Facebook tabs example 52 | 53 | 54 | navigate('Dynamic')} 57 | > 58 | Dynamic tabs example 59 | 60 | ; 61 | }, 62 | }); 63 | 64 | const App = StackNavigator({ 65 | Home: { screen: HomeScreen }, 66 | Simple: { screen: SimpleExample }, 67 | Scrollable: { screen: ScrollableTabsExample }, 68 | Overlay: { screen: OverlayExample }, 69 | Facebook: { screen: FacebookExample }, 70 | Dynamic: { screen: DynamicExample }, 71 | }); 72 | 73 | export default App; 74 | 75 | const styles = StyleSheet.create({ 76 | container: { 77 | flex: 1, 78 | marginTop: 30, 79 | alignItems: 'center', 80 | }, 81 | button: { 82 | padding: 10, 83 | }, 84 | }); 85 | -------------------------------------------------------------------------------- /Example/ios/ExampleTests/ExampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import 14 | #import 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface ExampleTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation ExampleTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /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 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Disabling obfuscation is useful if you collect stack traces from production crashes 20 | # (unless you are using a system that supports de-obfuscate the stack traces). 21 | -dontobfuscate 22 | 23 | # React Native 24 | 25 | # Keep our interfaces so they can be used by other ProGuard rules. 26 | # See http://sourceforge.net/p/proguard/bugs/466/ 27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip 28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters 29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 30 | 31 | # Do not strip any method/class that is annotated with @DoNotStrip 32 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 33 | -keep @com.facebook.common.internal.DoNotStrip class * 34 | -keepclassmembers class * { 35 | @com.facebook.proguard.annotations.DoNotStrip *; 36 | @com.facebook.common.internal.DoNotStrip *; 37 | } 38 | 39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 40 | void set*(***); 41 | *** get*(); 42 | } 43 | 44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 46 | -keepclassmembers,includedescriptorclasses class * { native ; } 47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } 49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } 50 | 51 | -dontwarn com.facebook.react.** 52 | 53 | # TextLayoutBuilder uses a non-public Android constructor within StaticLayout. 54 | # See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details. 55 | -dontwarn android.text.StaticLayout 56 | 57 | # okhttp 58 | 59 | -keepattributes Signature 60 | -keepattributes *Annotation* 61 | -keep class okhttp3.** { *; } 62 | -keep interface okhttp3.** { *; } 63 | -dontwarn okhttp3.** 64 | 65 | # okio 66 | 67 | -keep class sun.misc.Unsafe { *; } 68 | -dontwarn java.nio.file.* 69 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 70 | -dontwarn okio.** 71 | -------------------------------------------------------------------------------- /DefaultTabBar.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactNative = require('react-native'); 3 | const DeprecatedPropTypes = require('deprecated-react-native-prop-types'); 4 | const PropTypes = require('prop-types'); 5 | const createReactClass = require('create-react-class'); 6 | const { 7 | StyleSheet, 8 | Text, 9 | View, 10 | Animated, 11 | } = ReactNative; 12 | const Button = require('./Button'); 13 | 14 | const DefaultTabBar = createReactClass({ 15 | propTypes: { 16 | goToPage: PropTypes.func, 17 | activeTab: PropTypes.number, 18 | tabs: PropTypes.array, 19 | backgroundColor: PropTypes.string, 20 | activeTextColor: PropTypes.string, 21 | inactiveTextColor: PropTypes.string, 22 | textStyle: DeprecatedPropTypes.TextPropTypes.style, 23 | tabStyle: DeprecatedPropTypes.ViewPropTypes.style, 24 | renderTab: PropTypes.func, 25 | underlineStyle: DeprecatedPropTypes.ViewPropTypes.style, 26 | }, 27 | 28 | getDefaultProps() { 29 | return { 30 | activeTextColor: 'navy', 31 | inactiveTextColor: 'black', 32 | backgroundColor: null, 33 | }; 34 | }, 35 | 36 | renderTabOption(name, page) { 37 | }, 38 | 39 | renderTab(name, page, isTabActive, onPressHandler) { 40 | const { activeTextColor, inactiveTextColor, textStyle, } = this.props; 41 | const textColor = isTabActive ? activeTextColor : inactiveTextColor; 42 | const fontWeight = isTabActive ? 'bold' : 'normal'; 43 | 44 | return ; 58 | }, 59 | 60 | render() { 61 | const containerWidth = this.props.containerWidth; 62 | const numberOfTabs = this.props.tabs.length; 63 | const tabUnderlineStyle = { 64 | position: 'absolute', 65 | width: containerWidth / numberOfTabs, 66 | height: 4, 67 | backgroundColor: 'navy', 68 | bottom: 0, 69 | }; 70 | 71 | const translateX = this.props.scrollValue.interpolate({ 72 | inputRange: [0, 1], 73 | outputRange: [0, containerWidth / numberOfTabs], 74 | }); 75 | return ( 76 | 77 | {this.props.tabs.map((name, page) => { 78 | const isTabActive = this.props.activeTab === page; 79 | const renderTab = this.props.renderTab || this.renderTab; 80 | return renderTab(name, page, isTabActive, this.props.goToPage); 81 | })} 82 | 93 | 94 | ); 95 | }, 96 | }); 97 | 98 | const styles = StyleSheet.create({ 99 | tab: { 100 | flex: 1, 101 | alignItems: 'center', 102 | justifyContent: 'center', 103 | paddingBottom: 10, 104 | }, 105 | tabs: { 106 | height: 50, 107 | flexDirection: 'row', 108 | justifyContent: 'space-around', 109 | borderWidth: 1, 110 | borderTopWidth: 0, 111 | borderLeftWidth: 0, 112 | borderRightWidth: 0, 113 | borderColor: '#ccc', 114 | }, 115 | }); 116 | 117 | module.exports = DefaultTabBar; 118 | -------------------------------------------------------------------------------- /Example/ios/Example/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /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 19 | * entryFile: "index.android.js", 20 | * 21 | * // whether to bundle JS and assets in debug mode 22 | * bundleInDebug: false, 23 | * 24 | * // whether to bundle JS and assets in release mode 25 | * bundleInRelease: true, 26 | * 27 | * // whether to bundle JS and assets in another build variant (if configured). 28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 29 | * // The configuration property can be in the following formats 30 | * // 'bundleIn${productFlavor}${buildType}' 31 | * // 'bundleIn${buildType}' 32 | * // bundleInFreeDebug: true, 33 | * // bundleInPaidRelease: true, 34 | * // bundleInBeta: true, 35 | * 36 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 37 | * // for example: to disable dev mode in the staging build type (if configured) 38 | * devDisabledInStaging: true, 39 | * // The configuration property can be in the following formats 40 | * // 'devDisabledIn${productFlavor}${buildType}' 41 | * // 'devDisabledIn${buildType}' 42 | * 43 | * // the root of your project, i.e. where "package.json" lives 44 | * root: "../../", 45 | * 46 | * // where to put the JS bundle asset in debug mode 47 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 48 | * 49 | * // where to put the JS bundle asset in release mode 50 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 51 | * 52 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 53 | * // require('./image.png')), in debug mode 54 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 55 | * 56 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 57 | * // require('./image.png')), in release mode 58 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 59 | * 60 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 61 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 62 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 63 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 64 | * // for example, you might want to remove it from here. 65 | * inputExcludes: ["android/**", "ios/**"], 66 | * 67 | * // override which node gets called and with what additional arguments 68 | * nodeExecutableAndArgs: ["node"], 69 | * 70 | * // supply additional arguments to the packager 71 | * extraPackagerArgs: [] 72 | * ] 73 | */ 74 | 75 | apply from: "../../node_modules/react-native/react.gradle" 76 | 77 | /** 78 | * Set this to true to create two separate APKs instead of one: 79 | * - An APK that only works on ARM devices 80 | * - An APK that only works on x86 devices 81 | * The advantage is the size of the APK is reduced by about 4MB. 82 | * Upload all the APKs to the Play Store and people will download 83 | * the correct one based on the CPU architecture of their device. 84 | */ 85 | def enableSeparateBuildPerCPUArchitecture = false 86 | 87 | /** 88 | * Run Proguard to shrink the Java bytecode in release builds. 89 | */ 90 | def enableProguardInReleaseBuilds = false 91 | 92 | android { 93 | compileSdkVersion 23 94 | buildToolsVersion "23.0.1" 95 | 96 | defaultConfig { 97 | applicationId "com.example" 98 | minSdkVersion 16 99 | targetSdkVersion 22 100 | versionCode 1 101 | versionName "1.0" 102 | ndk { 103 | abiFilters "armeabi-v7a", "x86" 104 | } 105 | } 106 | splits { 107 | abi { 108 | reset() 109 | enable enableSeparateBuildPerCPUArchitecture 110 | universalApk false // If true, also generate a universal APK 111 | include "armeabi-v7a", "x86" 112 | } 113 | } 114 | buildTypes { 115 | release { 116 | minifyEnabled enableProguardInReleaseBuilds 117 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 118 | } 119 | } 120 | // applicationVariants are e.g. debug, release 121 | applicationVariants.all { variant -> 122 | variant.outputs.each { output -> 123 | // For each separate APK per architecture, set a unique version code as described here: 124 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits 125 | def versionCodes = ["armeabi-v7a":1, "x86":2] 126 | def abi = output.getFilter(OutputFile.ABI) 127 | if (abi != null) { // null for the universal-debug, universal-release variants 128 | output.versionCodeOverride = 129 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 130 | } 131 | } 132 | } 133 | } 134 | 135 | dependencies { 136 | compile project(':react-native-vector-icons') 137 | compile fileTree(dir: "libs", include: ["*.jar"]) 138 | compile "com.android.support:appcompat-v7:23.0.1" 139 | compile "com.facebook.react:react-native:+" // From node_modules 140 | } 141 | 142 | // Run this once to be able to run the application with BUCK 143 | // puts all compile dependencies into folder libs for BUCK to use 144 | task copyDownloadableDepsToLibs(type: Copy) { 145 | from configurations.compile 146 | into 'libs' 147 | } 148 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## react-native-scrollable-tab-view 3 | [![npm version](https://badge.fury.io/js/react-native-scrollable-tab-view.svg)](https://badge.fury.io/js/react-native-scrollable-tab-view) 4 | 5 | This is probably my favorite navigation pattern on Android, I wish it 6 | were more common on iOS! This is a very simple JavaScript-only 7 | implementation of it for React Native. For more information about how 8 | the animations behind this work, check out the Rebound section of the 9 | [React Native Animation Guide](https://facebook.github.io/react-native/docs/animations.html) 10 | 11 | 12 | ## Add it to your project 13 | 14 | 1. Run `npm install react-native-scrollable-tab-view --save` 15 | 2. `var ScrollableTabView = require('react-native-scrollable-tab-view');` 16 | 17 | ## Demo 18 | Run this example 19 | 20 | 21 | 22 | 23 | ## Basic usage 24 | 25 | ```javascript 26 | var ScrollableTabView = require('react-native-scrollable-tab-view'); 27 | 28 | var App = React.createClass({ 29 | render() { 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | } 38 | }); 39 | ``` 40 | 41 | ## Injecting a custom tab bar 42 | 43 | Suppose we had a custom tab bar called `CustomTabBar`, we would inject 44 | it into our `ScrollableTabView` like this: 45 | 46 | ```javascript 47 | var ScrollableTabView = require('react-native-scrollable-tab-view'); 48 | var CustomTabBar = require('./CustomTabBar'); 49 | 50 | var App = React.createClass({ 51 | render() { 52 | return ( 53 | }> 54 | 55 | 56 | 57 | 58 | ); 59 | } 60 | }); 61 | ``` 62 | To start you can just copy [DefaultTabBar](https://github.com/skv-headless/react-native-scrollable-tab-view/blob/master/DefaultTabBar.js). 63 | 64 | ## Examples 65 | 66 | [SimpleExample](https://github.com/skv-headless/react-native-scrollable-tab-view/blob/master/Example/SimpleExample.js). 67 | 68 | [ScrollableTabsExample](https://github.com/skv-headless/react-native-scrollable-tab-view/blob/master/Example/ScrollableTabsExample.js). 69 | 70 | [OverlayExample](https://github.com/skv-headless/react-native-scrollable-tab-view/blob/master/Example/OverlayExample.js). 71 | 72 | [FacebookExample](https://github.com/skv-headless/react-native-scrollable-tab-view/blob/master/Example/FacebookExample.js). 73 | 74 | ## Props 75 | 76 | - **`renderTabBar`** _(Function:ReactComponent)_ - accept 1 argument `props` and should return a component to use as 77 | the tab bar. The component has `goToPage`, `tabs`, `activeTab` and 78 | `ref` added to the props, and should implement `setAnimationValue` to 79 | be able to animate itself along with the tab content. You can manually pass the `props` to the TabBar component. 80 | - **`tabBarPosition`** _(String)_ Defaults to `"top"`. 81 | - `"bottom"` to position the tab bar below content. 82 | - `"overlayTop"` or `"overlayBottom"` for a semitransparent tab bar that overlays content. Custom tab bars must consume a style prop on their outer element to support this feature: `style={this.props.style}`. 83 | - **`onChangeTab`** _(Function)_ - function to call when tab changes, should accept 1 argument which is an Object containing two keys: `i`: the index of the tab that is selected, `ref`: the ref of the tab that is selected 84 | - **`onScroll`** _(Function)_ - function to call when the pages are sliding, should accept 1 argument which is an Float number representing the page position in the slide frame. 85 | - **`locked`** _(Bool)_ - disables horizontal dragging to scroll between tabs, default is false. 86 | - **`initialPage`** _(Integer)_ - the index of the initially selected tab, defaults to 0 === first tab. 87 | - **`page`** _(Integer)_ - set selected tab(can be buggy see [#126](https://github.com/brentvatne/react-native-scrollable-tab-view/issues/126) 88 | - **`children`** _(ReactComponents)_ - each top-level child component should have a `tabLabel` prop that can be used by the tab bar component to render out the labels. The default tab bar expects it to be a string, but you can use anything you want if you make a custom tab bar. 89 | - **`tabBarUnderlineStyle`** _([View.propTypes.style](https://facebook.github.io/react-native/docs/view.html#style))_ - style of the default tab bar's underline. 90 | - **`tabBarBackgroundColor`** _(String)_ - color of the default tab bar's background, defaults to `white` 91 | - **`tabBarActiveTextColor`** _(String)_ - color of the default tab bar's text when active, defaults to `navy` 92 | - **`tabBarInactiveTextColor`** _(String)_ - color of the default tab bar's text when inactive, defaults to `black` 93 | - **`tabBarTextStyle`** _(Object)_ - Additional styles to the tab bar's text. Example: `{fontFamily: 'Roboto', fontSize: 15}` 94 | - **`style`** _([View.propTypes.style](https://facebook.github.io/react-native/docs/view.html#style))_ 95 | - **`contentProps`** _(Object)_ - props that are applied to root `ScrollView`/`ViewPagerAndroid`. Note that overriding defaults set by the library may break functionality; see the source for details. 96 | - **`scrollWithoutAnimation`** _(Bool)_ - on tab press change tab without animation. 97 | - **`prerenderingSiblingsNumber`** _(Integer)_ - pre-render nearby # sibling, `Infinity` === render all the siblings, default to 0 === render current page. 98 | 99 | ## Contribution 100 | **Issues** are welcome. Please add a screenshot of bug and code snippet. Quickest way to solve issue is to reproduce it on one of the examples. 101 | 102 | **Pull requests** are welcome. If you want to change API or making something big better to create issue and discuss it first. Before submiting PR please run ```eslint .``` Also all eslint fixes are welcome. 103 | 104 | Please attach video or gif to PR's and issues it is super helpful. 105 | 106 | How to make video 107 | 108 | How to make gif from video 109 | 110 | --- 111 | 112 | **MIT Licensed** 113 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "jasmine": true 7 | }, 8 | "ecmaFeatures": { 9 | "arrowFunctions": true, 10 | "blockBindings": true, 11 | "classes": true, 12 | "defaultParams": true, 13 | "destructuring": true, 14 | "forOf": true, 15 | "generators": false, 16 | "modules": true, 17 | "objectLiteralComputedProperties": true, 18 | "objectLiteralDuplicateProperties": false, 19 | "objectLiteralShorthandMethods": true, 20 | "objectLiteralShorthandProperties": true, 21 | "spread": true, 22 | "superInFunctions": true, 23 | "templateStrings": true, 24 | "jsx": true 25 | }, 26 | "rules": { 27 | /** 28 | * Strict mode 29 | */ 30 | // babel inserts "use strict"; for us 31 | // http://eslint.org/docs/rules/strict 32 | "strict": [2, "never"], 33 | 34 | /** 35 | * ES6 36 | */ 37 | "no-var": 2, // http://eslint.org/docs/rules/no-var 38 | 39 | /** 40 | * Variables 41 | */ 42 | "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow 43 | "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names 44 | "no-unused-vars": [0, { // http://eslint.org/docs/rules/no-unused-vars 45 | "vars": "local", 46 | "args": "after-used" 47 | }], 48 | 49 | /** 50 | * Possible errors 51 | */ 52 | "comma-dangle": [2, "always"], // http://eslint.org/docs/rules/comma-dangle 53 | "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign 54 | "no-console": 1, // http://eslint.org/docs/rules/no-console 55 | "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger 56 | "no-alert": 1, // http://eslint.org/docs/rules/no-alert 57 | "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition 58 | "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys 59 | "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case 60 | "no-empty": 2, // http://eslint.org/docs/rules/no-empty 61 | "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign 62 | "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast 63 | "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi 64 | "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign 65 | "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations 66 | "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp 67 | "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace 68 | "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls 69 | "no-reserved-keys": 0, // http://eslint.org/docs/rules/no-reserved-keys 70 | "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays 71 | "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable 72 | "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan 73 | "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var 74 | 75 | /** 76 | * Best practices 77 | */ 78 | "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return 79 | "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly 80 | "default-case": 2, // http://eslint.org/docs/rules/default-case 81 | "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation 82 | "allowKeywords": true 83 | }], 84 | "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq 85 | "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in 86 | "no-caller": 2, // http://eslint.org/docs/rules/no-caller 87 | "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null 88 | "no-eval": 2, // http://eslint.org/docs/rules/no-eval 89 | "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native 90 | "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind 91 | "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough 92 | "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal 93 | "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval 94 | "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks 95 | "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func 96 | "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str 97 | "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign 98 | "no-new": 2, // http://eslint.org/docs/rules/no-new 99 | "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func 100 | "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers 101 | "no-octal": 2, // http://eslint.org/docs/rules/no-octal 102 | "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape 103 | "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign 104 | "no-proto": 2, // http://eslint.org/docs/rules/no-proto 105 | "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare 106 | "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign 107 | "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url 108 | "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare 109 | "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences 110 | "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal 111 | "no-with": 2, // http://eslint.org/docs/rules/no-with 112 | "radix": 2, // http://eslint.org/docs/rules/radix 113 | "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top 114 | "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife 115 | "yoda": 2, // http://eslint.org/docs/rules/yoda 116 | 117 | /** 118 | * Style 119 | */ 120 | "indent": [2, 2], // http://eslint.org/docs/rules/ 121 | "brace-style": [2, // http://eslint.org/docs/rules/brace-style 122 | "1tbs", { 123 | "allowSingleLine": true 124 | }], 125 | "quotes": [ 126 | 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes 127 | ], 128 | "camelcase": [2, { // http://eslint.org/docs/rules/camelcase 129 | "properties": "never" 130 | }], 131 | "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing 132 | "before": false, 133 | "after": true 134 | }], 135 | "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style 136 | "eol-last": 2, // http://eslint.org/docs/rules/eol-last 137 | "func-names": 1, // http://eslint.org/docs/rules/func-names 138 | "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing 139 | "beforeColon": false, 140 | "afterColon": true 141 | }], 142 | "new-cap": [2, { // http://eslint.org/docs/rules/new-cap 143 | "newIsCap": true 144 | }], 145 | "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines 146 | "max": 2 147 | }], 148 | "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary 149 | "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object 150 | "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func 151 | "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces 152 | "no-extra-parens": 0, // http://eslint.org/docs/rules/no-extra-parens 153 | "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle 154 | "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var 155 | "padded-blocks": 0, // http://eslint.org/docs/rules/padded-blocks 156 | "semi": [2, "always"], // http://eslint.org/docs/rules/semi 157 | "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing 158 | "before": false, 159 | "after": true 160 | }], 161 | "keyword-spacing": 2, // http://eslint.org/docs/rules/keyword-spacing 162 | "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks 163 | "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren 164 | "space-infix-ops": 2 // http://eslint.org/docs/rules/space-infix-ops 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /ScrollableTabBar.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactNative = require('react-native'); 3 | const DeprecatedPropTypes = require('deprecated-react-native-prop-types'); 4 | const PropTypes = require('prop-types'); 5 | const createReactClass = require('create-react-class'); 6 | const { 7 | View, 8 | Animated, 9 | StyleSheet, 10 | ScrollView, 11 | Text, 12 | Platform, 13 | Dimensions, 14 | } = ReactNative; 15 | const Button = require('./Button'); 16 | 17 | const WINDOW_WIDTH = Dimensions.get('window').width; 18 | 19 | const ScrollableTabBar = createReactClass({ 20 | propTypes: { 21 | goToPage: PropTypes.func, 22 | activeTab: PropTypes.number, 23 | tabs: PropTypes.array, 24 | backgroundColor: PropTypes.string, 25 | activeTextColor: PropTypes.string, 26 | inactiveTextColor: PropTypes.string, 27 | scrollOffset: PropTypes.number, 28 | style: DeprecatedPropTypes.ViewPropTypes.style, 29 | tabStyle: DeprecatedPropTypes.ViewPropTypes.style, 30 | tabsContainerStyle: DeprecatedPropTypes.ViewPropTypes.style, 31 | textStyle: DeprecatedPropTypes.TextPropTypes.style, 32 | renderTab: PropTypes.func, 33 | underlineStyle: DeprecatedPropTypes.ViewPropTypes.style, 34 | onScroll: PropTypes.func, 35 | }, 36 | 37 | getDefaultProps() { 38 | return { 39 | scrollOffset: 52, 40 | activeTextColor: 'navy', 41 | inactiveTextColor: 'black', 42 | backgroundColor: null, 43 | style: {}, 44 | tabStyle: {}, 45 | tabsContainerStyle: {}, 46 | underlineStyle: {}, 47 | }; 48 | }, 49 | 50 | getInitialState() { 51 | this._tabsMeasurements = []; 52 | return { 53 | _leftTabUnderline: new Animated.Value(0), 54 | _widthTabUnderline: new Animated.Value(0), 55 | _containerWidth: null, 56 | }; 57 | }, 58 | 59 | componentDidMount() { 60 | this.props.scrollValue.addListener(this.updateView); 61 | }, 62 | 63 | updateView(offset) { 64 | const position = Math.floor(offset.value); 65 | const pageOffset = offset.value % 1; 66 | const tabCount = this.props.tabs.length; 67 | const lastTabPosition = tabCount - 1; 68 | 69 | if (tabCount === 0 || offset.value < 0 || offset.value > lastTabPosition) { 70 | return; 71 | } 72 | 73 | if (this.necessarilyMeasurementsCompleted(position, position === lastTabPosition)) { 74 | this.updateTabPanel(position, pageOffset); 75 | this.updateTabUnderline(position, pageOffset, tabCount); 76 | } 77 | }, 78 | 79 | necessarilyMeasurementsCompleted(position, isLastTab) { 80 | return this._tabsMeasurements[position] && 81 | (isLastTab || this._tabsMeasurements[position + 1]) && 82 | this._tabContainerMeasurements && 83 | this._containerMeasurements; 84 | }, 85 | 86 | updateTabPanel(position, pageOffset) { 87 | const containerWidth = this._containerMeasurements.width; 88 | const tabWidth = this._tabsMeasurements[position].width; 89 | const nextTabMeasurements = this._tabsMeasurements[position + 1]; 90 | const nextTabWidth = nextTabMeasurements && nextTabMeasurements.width || 0; 91 | const tabOffset = this._tabsMeasurements[position].left; 92 | const absolutePageOffset = pageOffset * tabWidth; 93 | let newScrollX = tabOffset + absolutePageOffset; 94 | 95 | // center tab and smooth tab change (for when tabWidth changes a lot between two tabs) 96 | newScrollX -= (containerWidth - (1 - pageOffset) * tabWidth - pageOffset * nextTabWidth) / 2; 97 | newScrollX = newScrollX >= 0 ? newScrollX : 0; 98 | 99 | if (Platform.OS === 'android') { 100 | this._scrollView.scrollTo({x: newScrollX, y: 0, animated: false, }); 101 | } else { 102 | const rightBoundScroll = this._tabContainerMeasurements.width - (this._containerMeasurements.width); 103 | newScrollX = newScrollX > rightBoundScroll ? rightBoundScroll : newScrollX; 104 | this._scrollView.scrollTo({x: newScrollX, y: 0, animated: false, }); 105 | } 106 | 107 | }, 108 | 109 | updateTabUnderline(position, pageOffset, tabCount) { 110 | const lineLeft = this._tabsMeasurements[position].left; 111 | const lineRight = this._tabsMeasurements[position].right; 112 | 113 | if (position < tabCount - 1) { 114 | const nextTabLeft = this._tabsMeasurements[position + 1].left; 115 | const nextTabRight = this._tabsMeasurements[position + 1].right; 116 | 117 | const newLineLeft = (pageOffset * nextTabLeft + (1 - pageOffset) * lineLeft); 118 | const newLineRight = (pageOffset * nextTabRight + (1 - pageOffset) * lineRight); 119 | 120 | this.state._leftTabUnderline.setValue(newLineLeft); 121 | this.state._widthTabUnderline.setValue(newLineRight - newLineLeft); 122 | } else { 123 | this.state._leftTabUnderline.setValue(lineLeft); 124 | this.state._widthTabUnderline.setValue(lineRight - lineLeft); 125 | } 126 | }, 127 | 128 | renderTab(name, page, isTabActive, onPressHandler, onLayoutHandler) { 129 | const { activeTextColor, inactiveTextColor, textStyle, } = this.props; 130 | const textColor = isTabActive ? activeTextColor : inactiveTextColor; 131 | const fontWeight = isTabActive ? 'bold' : 'normal'; 132 | 133 | return ; 147 | }, 148 | 149 | measureTab(page, event) { 150 | const { x, width, height, } = event.nativeEvent.layout; 151 | this._tabsMeasurements[page] = {left: x, right: x + width, width, height, }; 152 | this.updateView({value: this.props.scrollValue.__getValue(), }); 153 | }, 154 | 155 | render() { 156 | const tabUnderlineStyle = { 157 | position: 'absolute', 158 | height: 4, 159 | backgroundColor: 'navy', 160 | bottom: 0, 161 | }; 162 | 163 | const dynamicTabUnderline = { 164 | left: this.state._leftTabUnderline, 165 | width: this.state._widthTabUnderline, 166 | }; 167 | 168 | const { 169 | onScroll, 170 | } = this.props; 171 | 172 | return 176 | { this._scrollView = scrollView; }} 178 | horizontal={true} 179 | showsHorizontalScrollIndicator={false} 180 | showsVerticalScrollIndicator={false} 181 | directionalLockEnabled={true} 182 | bounces={false} 183 | scrollsToTop={false} 184 | onScroll={onScroll} 185 | scrollEventThrottle={16} 186 | > 187 | 192 | {this.props.tabs.map((name, page) => { 193 | const isTabActive = this.props.activeTab === page; 194 | const renderTab = this.props.renderTab || this.renderTab; 195 | return renderTab(name, page, isTabActive, this.props.goToPage, this.measureTab.bind(this, page)); 196 | })} 197 | 198 | 199 | 200 | ; 201 | }, 202 | 203 | componentDidUpdate(prevProps) { 204 | // If the tabs change, force the width of the tabs container to be recalculated 205 | if (JSON.stringify(prevProps.tabs) !== JSON.stringify(this.props.tabs) && this.state._containerWidth) { 206 | this.setState({ _containerWidth: null, }); 207 | } 208 | }, 209 | 210 | onTabContainerLayout(e) { 211 | this._tabContainerMeasurements = e.nativeEvent.layout; 212 | let width = this._tabContainerMeasurements.width; 213 | if (width < WINDOW_WIDTH) { 214 | width = WINDOW_WIDTH; 215 | } 216 | this.setState({ _containerWidth: width, }); 217 | this.updateView({value: this.props.scrollValue.__getValue(), }); 218 | }, 219 | 220 | onContainerLayout(e) { 221 | this._containerMeasurements = e.nativeEvent.layout; 222 | this.updateView({value: this.props.scrollValue.__getValue(), }); 223 | }, 224 | }); 225 | 226 | module.exports = ScrollableTabBar; 227 | 228 | const styles = StyleSheet.create({ 229 | tab: { 230 | height: 49, 231 | alignItems: 'center', 232 | justifyContent: 'center', 233 | paddingLeft: 20, 234 | paddingRight: 20, 235 | }, 236 | container: { 237 | height: 50, 238 | borderWidth: 1, 239 | borderTopWidth: 0, 240 | borderLeftWidth: 0, 241 | borderRightWidth: 0, 242 | borderColor: '#ccc', 243 | }, 244 | tabs: { 245 | flexDirection: 'row', 246 | justifyContent: 'space-around', 247 | }, 248 | }); 249 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactNative = require('react-native'); 3 | const DeprecatedPropTypes = require('deprecated-react-native-prop-types'); 4 | const createReactClass = require('create-react-class'); 5 | const PropTypes = require('prop-types'); 6 | const { 7 | Dimensions, 8 | View, 9 | Animated, 10 | ScrollView, 11 | Platform, 12 | StyleSheet, 13 | InteractionManager, 14 | } = ReactNative; 15 | 16 | const ViewPagerAndroid = require('@react-native-community/viewpager'); 17 | const TimerMixin = require('react-timer-mixin'); 18 | const ViewPager = require('@react-native-community/viewpager'); 19 | 20 | const SceneComponent = require('./SceneComponent'); 21 | const DefaultTabBar = require('./DefaultTabBar'); 22 | const ScrollableTabBar = require('./ScrollableTabBar'); 23 | 24 | const AnimatedViewPagerAndroid = Platform.OS === 'android' ? 25 | Animated.createAnimatedComponent(ViewPager) : 26 | undefined; 27 | 28 | const ScrollableTabView = createReactClass({ 29 | mixins: [TimerMixin, ], 30 | statics: { 31 | DefaultTabBar, 32 | ScrollableTabBar, 33 | }, 34 | scrollOnMountCalled: false, 35 | tabWillChangeWithoutGesture: false, 36 | 37 | propTypes: { 38 | tabBarPosition: PropTypes.oneOf(['top', 'bottom', 'overlayTop', 'overlayBottom', ]), 39 | initialPage: PropTypes.number, 40 | page: PropTypes.number, 41 | onChangeTab: PropTypes.func, 42 | onScroll: PropTypes.func, 43 | renderTabBar: PropTypes.any, 44 | tabBarUnderlineStyle: DeprecatedPropTypes.ViewPropTypes.style, 45 | tabBarBackgroundColor: PropTypes.string, 46 | tabBarActiveTextColor: PropTypes.string, 47 | tabBarInactiveTextColor: PropTypes.string, 48 | tabBarTextStyle: PropTypes.object, 49 | style: DeprecatedPropTypes.ViewPropTypes.style, 50 | contentProps: PropTypes.object, 51 | scrollWithoutAnimation: PropTypes.bool, 52 | locked: PropTypes.bool, 53 | prerenderingSiblingsNumber: PropTypes.number, 54 | }, 55 | 56 | getDefaultProps() { 57 | return { 58 | tabBarPosition: 'top', 59 | initialPage: 0, 60 | page: -1, 61 | onChangeTab: () => {}, 62 | onScroll: () => {}, 63 | contentProps: {}, 64 | scrollWithoutAnimation: false, 65 | locked: false, 66 | prerenderingSiblingsNumber: 0, 67 | }; 68 | }, 69 | 70 | getInitialState() { 71 | const containerWidth = Dimensions.get('window').width; 72 | let scrollValue; 73 | let scrollXIOS; 74 | let positionAndroid; 75 | let offsetAndroid; 76 | 77 | if (Platform.OS === 'ios') { 78 | scrollXIOS = new Animated.Value(this.props.initialPage * containerWidth); 79 | const containerWidthAnimatedValue = new Animated.Value(containerWidth); 80 | // Need to call __makeNative manually to avoid a native animated bug. See 81 | // https://github.com/facebook/react-native/pull/14435 82 | containerWidthAnimatedValue.__makeNative(); 83 | scrollValue = Animated.divide(scrollXIOS, containerWidthAnimatedValue); 84 | 85 | const callListeners = this._polyfillAnimatedValue(scrollValue); 86 | scrollXIOS.addListener( 87 | ({ value, }) => callListeners(value / this.state.containerWidth) 88 | ); 89 | } else { 90 | positionAndroid = new Animated.Value(this.props.initialPage); 91 | offsetAndroid = new Animated.Value(0); 92 | scrollValue = Animated.add(positionAndroid, offsetAndroid); 93 | 94 | const callListeners = this._polyfillAnimatedValue(scrollValue); 95 | let positionAndroidValue = this.props.initialPage; 96 | let offsetAndroidValue = 0; 97 | positionAndroid.addListener(({ value, }) => { 98 | positionAndroidValue = value; 99 | callListeners(positionAndroidValue + offsetAndroidValue); 100 | }); 101 | offsetAndroid.addListener(({ value, }) => { 102 | offsetAndroidValue = value; 103 | callListeners(positionAndroidValue + offsetAndroidValue); 104 | }); 105 | } 106 | 107 | return { 108 | currentPage: this.props.initialPage, 109 | scrollValue, 110 | scrollXIOS, 111 | positionAndroid, 112 | offsetAndroid, 113 | containerWidth, 114 | sceneKeys: this.newSceneKeys({ currentPage: this.props.initialPage, }), 115 | }; 116 | }, 117 | 118 | componentDidUpdate(prevProps) { 119 | if (this.props.children !== prevProps.children) { 120 | this.updateSceneKeys({ page: this.state.currentPage, children: this.props.children, }); 121 | } 122 | 123 | if (this.props.page >= 0 && this.props.page !== this.state.currentPage) { 124 | this.goToPage(this.props.page); 125 | } 126 | }, 127 | 128 | componentWillUnmount() { 129 | if (Platform.OS === 'ios') { 130 | this.state.scrollXIOS.removeAllListeners(); 131 | } else { 132 | this.state.positionAndroid.removeAllListeners(); 133 | this.state.offsetAndroid.removeAllListeners(); 134 | } 135 | }, 136 | 137 | goToPage(pageNumber) { 138 | if (Platform.OS === 'ios') { 139 | const offset = pageNumber * this.state.containerWidth; 140 | if (this.scrollView) { 141 | this.scrollView.scrollTo({x: offset, y: 0, animated: !this.props.scrollWithoutAnimation, }); 142 | } 143 | } else { 144 | if (this.scrollView) { 145 | this.tabWillChangeWithoutGesture = true; 146 | if (this.props.scrollWithoutAnimation) { 147 | this.scrollView.setPageWithoutAnimation(pageNumber); 148 | } else { 149 | this.scrollView.setPage(pageNumber); 150 | } 151 | } 152 | } 153 | 154 | const currentPage = this.state.currentPage; 155 | this.updateSceneKeys({ 156 | page: pageNumber, 157 | callback: this._onChangeTab.bind(this, currentPage, pageNumber), 158 | }); 159 | }, 160 | 161 | renderTabBar(props) { 162 | if (this.props.renderTabBar === false) { 163 | return null; 164 | } else if (this.props.renderTabBar) { 165 | return React.cloneElement(this.props.renderTabBar(props), props); 166 | } else { 167 | return ; 168 | } 169 | }, 170 | 171 | updateSceneKeys({ page, children = this.props.children, callback = () => {}, }) { 172 | let newKeys = this.newSceneKeys({ previousKeys: this.state.sceneKeys, currentPage: page, children, }); 173 | this.setState({currentPage: page, sceneKeys: newKeys, }, callback); 174 | }, 175 | 176 | newSceneKeys({ previousKeys = [], currentPage = 0, children = this.props.children, }) { 177 | let newKeys = []; 178 | this._children(children).forEach((child, idx) => { 179 | let key = this._makeSceneKey(child, idx); 180 | if (this._keyExists(previousKeys, key) || 181 | this._shouldRenderSceneKey(idx, currentPage)) { 182 | newKeys.push(key); 183 | } 184 | }); 185 | return newKeys; 186 | }, 187 | 188 | // Animated.add and Animated.divide do not currently support listeners so 189 | // we have to polyfill it here since a lot of code depends on being able 190 | // to add a listener to `scrollValue`. See https://github.com/facebook/react-native/pull/12620. 191 | _polyfillAnimatedValue(animatedValue) { 192 | 193 | const listeners = new Set(); 194 | const addListener = (listener) => { 195 | listeners.add(listener); 196 | }; 197 | 198 | const removeListener = (listener) => { 199 | listeners.delete(listener); 200 | }; 201 | 202 | const removeAllListeners = () => { 203 | listeners.clear(); 204 | }; 205 | 206 | animatedValue.addListener = addListener; 207 | animatedValue.removeListener = removeListener; 208 | animatedValue.removeAllListeners = removeAllListeners; 209 | 210 | return (value) => listeners.forEach(listener => listener({ value, })); 211 | }, 212 | 213 | _shouldRenderSceneKey(idx, currentPageKey) { 214 | let numOfSibling = this.props.prerenderingSiblingsNumber; 215 | return (idx < (currentPageKey + numOfSibling + 1) && 216 | idx > (currentPageKey - numOfSibling - 1)); 217 | }, 218 | 219 | _keyExists(sceneKeys, key) { 220 | return sceneKeys.find((sceneKey) => key === sceneKey); 221 | }, 222 | 223 | _makeSceneKey(child, idx) { 224 | return child.props.tabLabel + '_' + idx; 225 | }, 226 | 227 | renderScrollableContent() { 228 | if (Platform.OS === 'ios') { 229 | const scenes = this._composeScenes(); 230 | return { this.scrollView = scrollView; }} 236 | onScroll={Animated.event( 237 | [{ nativeEvent: { contentOffset: { x: this.state.scrollXIOS, }, }, }, ], 238 | { useNativeDriver: true, listener: this._onScroll, } 239 | )} 240 | onMomentumScrollBegin={this._onMomentumScrollBeginAndEnd} 241 | onMomentumScrollEnd={this._onMomentumScrollBeginAndEnd} 242 | scrollEventThrottle={16} 243 | scrollsToTop={false} 244 | showsHorizontalScrollIndicator={false} 245 | scrollEnabled={!this.props.locked} 246 | directionalLockEnabled 247 | alwaysBounceVertical={false} 248 | keyboardDismissMode="on-drag" 249 | {...this.props.contentProps} 250 | > 251 | {scenes} 252 | ; 253 | } else { 254 | const scenes = this._composeScenes(); 255 | return { this.scrollView = scrollView; }} 275 | {...this.props.contentProps} 276 | > 277 | {scenes} 278 | ; 279 | } 280 | }, 281 | 282 | _composeScenes() { 283 | return this._children().map((child, idx) => { 284 | let key = this._makeSceneKey(child, idx); 285 | return 290 | {this._keyExists(this.state.sceneKeys, key) ? child : } 291 | ; 292 | }); 293 | }, 294 | 295 | _onMomentumScrollBeginAndEnd(e) { 296 | const offsetX = e.nativeEvent.contentOffset.x; 297 | const page = Math.round(offsetX / this.state.containerWidth); 298 | if (this.state.currentPage !== page) { 299 | this._updateSelectedPage(page); 300 | } 301 | }, 302 | 303 | _updateSelectedPage(nextPage) { 304 | let localNextPage = nextPage; 305 | if (typeof localNextPage === 'object') { 306 | localNextPage = nextPage.nativeEvent.position; 307 | } 308 | 309 | const currentPage = this.state.currentPage; 310 | !this.tabWillChangeWithoutGesture && this.updateSceneKeys({ 311 | page: localNextPage, 312 | callback: this._onChangeTab.bind(this, currentPage, localNextPage), 313 | }); 314 | this.tabWillChangeWithoutGesture = false; 315 | }, 316 | 317 | _onChangeTab(prevPage, currentPage) { 318 | this.props.onChangeTab({ 319 | i: currentPage, 320 | ref: this._children()[currentPage], 321 | from: prevPage, 322 | }); 323 | }, 324 | 325 | _onScroll(e) { 326 | if (Platform.OS === 'ios') { 327 | const offsetX = e.nativeEvent.contentOffset.x; 328 | if (offsetX === 0 && !this.scrollOnMountCalled) { 329 | this.scrollOnMountCalled = true; 330 | } else { 331 | this.props.onScroll(offsetX / this.state.containerWidth); 332 | } 333 | } else { 334 | const { position, offset, } = e.nativeEvent; 335 | this.props.onScroll(position + offset); 336 | } 337 | }, 338 | 339 | _handleLayout(e) { 340 | const { width, } = e.nativeEvent.layout; 341 | 342 | if (!width || width <= 0 || Math.round(width) === Math.round(this.state.containerWidth)) { 343 | return; 344 | } 345 | 346 | if (Platform.OS === 'ios') { 347 | const containerWidthAnimatedValue = new Animated.Value(width); 348 | // Need to call __makeNative manually to avoid a native animated bug. See 349 | // https://github.com/facebook/react-native/pull/14435 350 | containerWidthAnimatedValue.__makeNative(); 351 | scrollValue = Animated.divide(this.state.scrollXIOS, containerWidthAnimatedValue); 352 | this.setState({ containerWidth: width, scrollValue, }); 353 | } else { 354 | this.setState({ containerWidth: width, }); 355 | } 356 | this.requestAnimationFrame(() => { 357 | this.goToPage(this.state.currentPage); 358 | }); 359 | }, 360 | 361 | _children(children = this.props.children) { 362 | return React.Children.map(children, (child) => child); 363 | }, 364 | 365 | render() { 366 | let overlayTabs = (this.props.tabBarPosition === 'overlayTop' || this.props.tabBarPosition === 'overlayBottom'); 367 | let tabBarProps = { 368 | goToPage: this.goToPage, 369 | tabs: this._children().map((child) => child.props.tabLabel), 370 | activeTab: this.state.currentPage, 371 | scrollValue: this.state.scrollValue, 372 | containerWidth: this.state.containerWidth, 373 | }; 374 | 375 | if (this.props.tabBarBackgroundColor) { 376 | tabBarProps.backgroundColor = this.props.tabBarBackgroundColor; 377 | } 378 | if (this.props.tabBarActiveTextColor) { 379 | tabBarProps.activeTextColor = this.props.tabBarActiveTextColor; 380 | } 381 | if (this.props.tabBarInactiveTextColor) { 382 | tabBarProps.inactiveTextColor = this.props.tabBarInactiveTextColor; 383 | } 384 | if (this.props.tabBarTextStyle) { 385 | tabBarProps.textStyle = this.props.tabBarTextStyle; 386 | } 387 | if (this.props.tabBarUnderlineStyle) { 388 | tabBarProps.underlineStyle = this.props.tabBarUnderlineStyle; 389 | } 390 | if (overlayTabs) { 391 | tabBarProps.style = { 392 | position: 'absolute', 393 | left: 0, 394 | right: 0, 395 | [this.props.tabBarPosition === 'overlayTop' ? 'top' : 'bottom']: 0, 396 | }; 397 | } 398 | 399 | return 400 | {this.props.tabBarPosition === 'top' && this.renderTabBar(tabBarProps)} 401 | {this.renderScrollableContent()} 402 | {(this.props.tabBarPosition === 'bottom' || overlayTabs) && this.renderTabBar(tabBarProps)} 403 | ; 404 | }, 405 | }); 406 | 407 | module.exports = ScrollableTabView; 408 | 409 | const styles = StyleSheet.create({ 410 | container: { 411 | flex: 1, 412 | }, 413 | scrollableContentAndroid: { 414 | flex: 1, 415 | }, 416 | }); 417 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@react-native-community/viewpager@3.3.0": 6 | version "3.3.0" 7 | resolved "https://registry.yarnpkg.com/@react-native-community/viewpager/-/viewpager-3.3.0.tgz#e613747a43a31a6f3278f817ba96fdaaa7941f23" 8 | integrity sha512-tyzh79l4t/hxiyS9QD3LRmWMs8KVkZzjrkQ8U8+8To1wmvVCBtp8BenvNsDLTBO7CpO/YmiThpmIdEZMr1WuVw== 9 | 10 | "@react-native/normalize-color@*": 11 | version "2.0.0" 12 | resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.0.0.tgz#da955909432474a9a0fe1cbffc66576a0447f567" 13 | integrity sha512-Wip/xsc5lw8vsBlmY2MO/gFLp3MvuZ2baBZjDeTjjndMgM0h5sxz7AZR62RDPGgstp8Np7JzjvVqVT7tpFZqsw== 14 | 15 | acorn-jsx@^3.0.0: 16 | version "3.0.1" 17 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" 18 | integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= 19 | dependencies: 20 | acorn "^3.0.4" 21 | 22 | acorn@^3.0.4: 23 | version "3.3.0" 24 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" 25 | integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= 26 | 27 | acorn@^5.5.0: 28 | version "5.7.3" 29 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" 30 | integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== 31 | 32 | ajv-keywords@^1.0.0: 33 | version "1.5.1" 34 | resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" 35 | integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= 36 | 37 | ajv@^4.7.0: 38 | version "4.11.8" 39 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" 40 | integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= 41 | dependencies: 42 | co "^4.6.0" 43 | json-stable-stringify "^1.0.1" 44 | 45 | ansi-escapes@^1.1.0: 46 | version "1.4.0" 47 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 48 | integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= 49 | 50 | ansi-regex@^2.0.0: 51 | version "2.1.1" 52 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 53 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 54 | 55 | ansi-regex@^3.0.0: 56 | version "3.0.0" 57 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 58 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 59 | 60 | ansi-styles@^2.2.1: 61 | version "2.2.1" 62 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 63 | integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= 64 | 65 | argparse@^1.0.7: 66 | version "1.0.10" 67 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 68 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 69 | dependencies: 70 | sprintf-js "~1.0.2" 71 | 72 | asap@~2.0.3: 73 | version "2.0.6" 74 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 75 | integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= 76 | 77 | babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: 78 | version "6.26.0" 79 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 80 | integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= 81 | dependencies: 82 | chalk "^1.1.3" 83 | esutils "^2.0.2" 84 | js-tokens "^3.0.2" 85 | 86 | babel-eslint@^6.1.2: 87 | version "6.1.2" 88 | resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-6.1.2.tgz#5293419fe3672d66598d327da9694567ba6a5f2f" 89 | integrity sha1-UpNBn+NnLWZZjTJ9qWlFZ7pqXy8= 90 | dependencies: 91 | babel-traverse "^6.0.20" 92 | babel-types "^6.0.19" 93 | babylon "^6.0.18" 94 | lodash.assign "^4.0.0" 95 | lodash.pickby "^4.0.0" 96 | 97 | babel-messages@^6.23.0: 98 | version "6.23.0" 99 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" 100 | integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= 101 | dependencies: 102 | babel-runtime "^6.22.0" 103 | 104 | babel-runtime@^6.22.0, babel-runtime@^6.26.0: 105 | version "6.26.0" 106 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" 107 | integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= 108 | dependencies: 109 | core-js "^2.4.0" 110 | regenerator-runtime "^0.11.0" 111 | 112 | babel-traverse@^6.0.20: 113 | version "6.26.0" 114 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" 115 | integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= 116 | dependencies: 117 | babel-code-frame "^6.26.0" 118 | babel-messages "^6.23.0" 119 | babel-runtime "^6.26.0" 120 | babel-types "^6.26.0" 121 | babylon "^6.18.0" 122 | debug "^2.6.8" 123 | globals "^9.18.0" 124 | invariant "^2.2.2" 125 | lodash "^4.17.4" 126 | 127 | babel-types@^6.0.19, babel-types@^6.26.0: 128 | version "6.26.0" 129 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" 130 | integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= 131 | dependencies: 132 | babel-runtime "^6.26.0" 133 | esutils "^2.0.2" 134 | lodash "^4.17.4" 135 | to-fast-properties "^1.0.3" 136 | 137 | babylon@^6.0.18, babylon@^6.18.0: 138 | version "6.18.0" 139 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" 140 | integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== 141 | 142 | balanced-match@^1.0.0: 143 | version "1.0.0" 144 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 145 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 146 | 147 | brace-expansion@^1.1.7: 148 | version "1.1.11" 149 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 150 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 151 | dependencies: 152 | balanced-match "^1.0.0" 153 | concat-map "0.0.1" 154 | 155 | buffer-from@^1.0.0: 156 | version "1.1.1" 157 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 158 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 159 | 160 | caller-path@^0.1.0: 161 | version "0.1.0" 162 | resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" 163 | integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= 164 | dependencies: 165 | callsites "^0.2.0" 166 | 167 | callsites@^0.2.0: 168 | version "0.2.0" 169 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" 170 | integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= 171 | 172 | chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: 173 | version "1.1.3" 174 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 175 | integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= 176 | dependencies: 177 | ansi-styles "^2.2.1" 178 | escape-string-regexp "^1.0.2" 179 | has-ansi "^2.0.0" 180 | strip-ansi "^3.0.0" 181 | supports-color "^2.0.0" 182 | 183 | circular-json@^0.3.1: 184 | version "0.3.3" 185 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" 186 | integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== 187 | 188 | cli-cursor@^1.0.1: 189 | version "1.0.2" 190 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 191 | integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= 192 | dependencies: 193 | restore-cursor "^1.0.1" 194 | 195 | cli-width@^2.0.0: 196 | version "2.2.0" 197 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" 198 | integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= 199 | 200 | co@^4.6.0: 201 | version "4.6.0" 202 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 203 | integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= 204 | 205 | code-point-at@^1.0.0: 206 | version "1.1.0" 207 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 208 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 209 | 210 | concat-map@0.0.1: 211 | version "0.0.1" 212 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 213 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 214 | 215 | concat-stream@^1.5.2: 216 | version "1.6.2" 217 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" 218 | integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 219 | dependencies: 220 | buffer-from "^1.0.0" 221 | inherits "^2.0.3" 222 | readable-stream "^2.2.2" 223 | typedarray "^0.0.6" 224 | 225 | core-js@^1.0.0: 226 | version "1.2.7" 227 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" 228 | integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= 229 | 230 | core-js@^2.4.0: 231 | version "2.6.9" 232 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" 233 | integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== 234 | 235 | core-util-is@~1.0.0: 236 | version "1.0.2" 237 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 238 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 239 | 240 | create-react-class@^15.6.2: 241 | version "15.6.3" 242 | resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" 243 | integrity sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg== 244 | dependencies: 245 | fbjs "^0.8.9" 246 | loose-envify "^1.3.1" 247 | object-assign "^4.1.1" 248 | 249 | d@1, d@^1.0.1: 250 | version "1.0.1" 251 | resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" 252 | integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== 253 | dependencies: 254 | es5-ext "^0.10.50" 255 | type "^1.0.1" 256 | 257 | debug@^2.1.1, debug@^2.6.8: 258 | version "2.6.9" 259 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 260 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 261 | dependencies: 262 | ms "2.0.0" 263 | 264 | deep-is@~0.1.3: 265 | version "0.1.3" 266 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 267 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 268 | 269 | deprecated-react-native-prop-types@^2.3.0: 270 | version "2.3.0" 271 | resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz#c10c6ee75ff2b6de94bb127f142b814e6e08d9ab" 272 | integrity sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA== 273 | dependencies: 274 | "@react-native/normalize-color" "*" 275 | invariant "*" 276 | prop-types "*" 277 | 278 | doctrine@^2.0.0: 279 | version "2.1.0" 280 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" 281 | integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== 282 | dependencies: 283 | esutils "^2.0.2" 284 | 285 | encoding@^0.1.11: 286 | version "0.1.12" 287 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 288 | integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= 289 | dependencies: 290 | iconv-lite "~0.4.13" 291 | 292 | es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@~0.10.14: 293 | version "0.10.51" 294 | resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f" 295 | integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ== 296 | dependencies: 297 | es6-iterator "~2.0.3" 298 | es6-symbol "~3.1.1" 299 | next-tick "^1.0.0" 300 | 301 | es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: 302 | version "2.0.3" 303 | resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" 304 | integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= 305 | dependencies: 306 | d "1" 307 | es5-ext "^0.10.35" 308 | es6-symbol "^3.1.1" 309 | 310 | es6-map@^0.1.3: 311 | version "0.1.5" 312 | resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" 313 | integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= 314 | dependencies: 315 | d "1" 316 | es5-ext "~0.10.14" 317 | es6-iterator "~2.0.1" 318 | es6-set "~0.1.5" 319 | es6-symbol "~3.1.1" 320 | event-emitter "~0.3.5" 321 | 322 | es6-set@~0.1.5: 323 | version "0.1.5" 324 | resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" 325 | integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= 326 | dependencies: 327 | d "1" 328 | es5-ext "~0.10.14" 329 | es6-iterator "~2.0.1" 330 | es6-symbol "3.1.1" 331 | event-emitter "~0.3.5" 332 | 333 | es6-symbol@3.1.1: 334 | version "3.1.1" 335 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" 336 | integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= 337 | dependencies: 338 | d "1" 339 | es5-ext "~0.10.14" 340 | 341 | es6-symbol@^3.1.1, es6-symbol@~3.1.1: 342 | version "3.1.2" 343 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1" 344 | integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ== 345 | dependencies: 346 | d "^1.0.1" 347 | es5-ext "^0.10.51" 348 | 349 | es6-weak-map@^2.0.1: 350 | version "2.0.3" 351 | resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" 352 | integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== 353 | dependencies: 354 | d "1" 355 | es5-ext "^0.10.46" 356 | es6-iterator "^2.0.3" 357 | es6-symbol "^3.1.1" 358 | 359 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 360 | version "1.0.5" 361 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 362 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 363 | 364 | escope@^3.6.0: 365 | version "3.6.0" 366 | resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" 367 | integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= 368 | dependencies: 369 | es6-map "^0.1.3" 370 | es6-weak-map "^2.0.1" 371 | esrecurse "^4.1.0" 372 | estraverse "^4.1.1" 373 | 374 | eslint@^3.1.1: 375 | version "3.19.0" 376 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" 377 | integrity sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw= 378 | dependencies: 379 | babel-code-frame "^6.16.0" 380 | chalk "^1.1.3" 381 | concat-stream "^1.5.2" 382 | debug "^2.1.1" 383 | doctrine "^2.0.0" 384 | escope "^3.6.0" 385 | espree "^3.4.0" 386 | esquery "^1.0.0" 387 | estraverse "^4.2.0" 388 | esutils "^2.0.2" 389 | file-entry-cache "^2.0.0" 390 | glob "^7.0.3" 391 | globals "^9.14.0" 392 | ignore "^3.2.0" 393 | imurmurhash "^0.1.4" 394 | inquirer "^0.12.0" 395 | is-my-json-valid "^2.10.0" 396 | is-resolvable "^1.0.0" 397 | js-yaml "^3.5.1" 398 | json-stable-stringify "^1.0.0" 399 | levn "^0.3.0" 400 | lodash "^4.0.0" 401 | mkdirp "^0.5.0" 402 | natural-compare "^1.4.0" 403 | optionator "^0.8.2" 404 | path-is-inside "^1.0.1" 405 | pluralize "^1.2.1" 406 | progress "^1.1.8" 407 | require-uncached "^1.0.2" 408 | shelljs "^0.7.5" 409 | strip-bom "^3.0.0" 410 | strip-json-comments "~2.0.1" 411 | table "^3.7.8" 412 | text-table "~0.2.0" 413 | user-home "^2.0.0" 414 | 415 | espree@^3.4.0: 416 | version "3.5.4" 417 | resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" 418 | integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== 419 | dependencies: 420 | acorn "^5.5.0" 421 | acorn-jsx "^3.0.0" 422 | 423 | esprima@^4.0.0: 424 | version "4.0.1" 425 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 426 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 427 | 428 | esquery@^1.0.0: 429 | version "1.0.1" 430 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" 431 | integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== 432 | dependencies: 433 | estraverse "^4.0.0" 434 | 435 | esrecurse@^4.1.0: 436 | version "4.2.1" 437 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" 438 | integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== 439 | dependencies: 440 | estraverse "^4.1.0" 441 | 442 | estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: 443 | version "4.3.0" 444 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 445 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 446 | 447 | esutils@^2.0.2: 448 | version "2.0.3" 449 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 450 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 451 | 452 | event-emitter@~0.3.5: 453 | version "0.3.5" 454 | resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" 455 | integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= 456 | dependencies: 457 | d "1" 458 | es5-ext "~0.10.14" 459 | 460 | exit-hook@^1.0.0: 461 | version "1.1.1" 462 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 463 | integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= 464 | 465 | fast-levenshtein@~2.0.4: 466 | version "2.0.6" 467 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 468 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 469 | 470 | fbjs@^0.8.9: 471 | version "0.8.17" 472 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" 473 | integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= 474 | dependencies: 475 | core-js "^1.0.0" 476 | isomorphic-fetch "^2.1.1" 477 | loose-envify "^1.0.0" 478 | object-assign "^4.1.0" 479 | promise "^7.1.1" 480 | setimmediate "^1.0.5" 481 | ua-parser-js "^0.7.18" 482 | 483 | figures@^1.3.5: 484 | version "1.7.0" 485 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 486 | integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= 487 | dependencies: 488 | escape-string-regexp "^1.0.5" 489 | object-assign "^4.1.0" 490 | 491 | file-entry-cache@^2.0.0: 492 | version "2.0.0" 493 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" 494 | integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= 495 | dependencies: 496 | flat-cache "^1.2.1" 497 | object-assign "^4.0.1" 498 | 499 | flat-cache@^1.2.1: 500 | version "1.3.4" 501 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" 502 | integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== 503 | dependencies: 504 | circular-json "^0.3.1" 505 | graceful-fs "^4.1.2" 506 | rimraf "~2.6.2" 507 | write "^0.2.1" 508 | 509 | fs.realpath@^1.0.0: 510 | version "1.0.0" 511 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 512 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 513 | 514 | generate-function@^2.0.0: 515 | version "2.3.1" 516 | resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" 517 | integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== 518 | dependencies: 519 | is-property "^1.0.2" 520 | 521 | generate-object-property@^1.1.0: 522 | version "1.2.0" 523 | resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" 524 | integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= 525 | dependencies: 526 | is-property "^1.0.0" 527 | 528 | glob@^7.0.0, glob@^7.0.3, glob@^7.1.3: 529 | version "7.1.4" 530 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" 531 | integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== 532 | dependencies: 533 | fs.realpath "^1.0.0" 534 | inflight "^1.0.4" 535 | inherits "2" 536 | minimatch "^3.0.4" 537 | once "^1.3.0" 538 | path-is-absolute "^1.0.0" 539 | 540 | globals@^9.14.0, globals@^9.18.0: 541 | version "9.18.0" 542 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" 543 | integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== 544 | 545 | graceful-fs@^4.1.2: 546 | version "4.2.2" 547 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" 548 | integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== 549 | 550 | has-ansi@^2.0.0: 551 | version "2.0.0" 552 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 553 | integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= 554 | dependencies: 555 | ansi-regex "^2.0.0" 556 | 557 | iconv-lite@~0.4.13: 558 | version "0.4.24" 559 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 560 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 561 | dependencies: 562 | safer-buffer ">= 2.1.2 < 3" 563 | 564 | ignore@^3.2.0: 565 | version "3.3.10" 566 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" 567 | integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== 568 | 569 | imurmurhash@^0.1.4: 570 | version "0.1.4" 571 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 572 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 573 | 574 | inflight@^1.0.4: 575 | version "1.0.6" 576 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 577 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 578 | dependencies: 579 | once "^1.3.0" 580 | wrappy "1" 581 | 582 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 583 | version "2.0.4" 584 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 585 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 586 | 587 | inquirer@^0.12.0: 588 | version "0.12.0" 589 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" 590 | integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= 591 | dependencies: 592 | ansi-escapes "^1.1.0" 593 | ansi-regex "^2.0.0" 594 | chalk "^1.0.0" 595 | cli-cursor "^1.0.1" 596 | cli-width "^2.0.0" 597 | figures "^1.3.5" 598 | lodash "^4.3.0" 599 | readline2 "^1.0.1" 600 | run-async "^0.1.0" 601 | rx-lite "^3.1.2" 602 | string-width "^1.0.1" 603 | strip-ansi "^3.0.0" 604 | through "^2.3.6" 605 | 606 | interpret@^1.0.0: 607 | version "1.2.0" 608 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" 609 | integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== 610 | 611 | invariant@*, invariant@^2.2.2: 612 | version "2.2.4" 613 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" 614 | integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== 615 | dependencies: 616 | loose-envify "^1.0.0" 617 | 618 | is-fullwidth-code-point@^1.0.0: 619 | version "1.0.0" 620 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 621 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 622 | dependencies: 623 | number-is-nan "^1.0.0" 624 | 625 | is-fullwidth-code-point@^2.0.0: 626 | version "2.0.0" 627 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 628 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 629 | 630 | is-my-ip-valid@^1.0.0: 631 | version "1.0.0" 632 | resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" 633 | integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== 634 | 635 | is-my-json-valid@^2.10.0: 636 | version "2.20.0" 637 | resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" 638 | integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== 639 | dependencies: 640 | generate-function "^2.0.0" 641 | generate-object-property "^1.1.0" 642 | is-my-ip-valid "^1.0.0" 643 | jsonpointer "^4.0.0" 644 | xtend "^4.0.0" 645 | 646 | is-property@^1.0.0, is-property@^1.0.2: 647 | version "1.0.2" 648 | resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" 649 | integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= 650 | 651 | is-resolvable@^1.0.0: 652 | version "1.1.0" 653 | resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" 654 | integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== 655 | 656 | is-stream@^1.0.1: 657 | version "1.1.0" 658 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 659 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 660 | 661 | isarray@~1.0.0: 662 | version "1.0.0" 663 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 664 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 665 | 666 | isomorphic-fetch@^2.1.1: 667 | version "2.2.1" 668 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 669 | integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= 670 | dependencies: 671 | node-fetch "^1.0.1" 672 | whatwg-fetch ">=0.10.0" 673 | 674 | "js-tokens@^3.0.0 || ^4.0.0": 675 | version "4.0.0" 676 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 677 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 678 | 679 | js-tokens@^3.0.2: 680 | version "3.0.2" 681 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 682 | integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= 683 | 684 | js-yaml@^3.5.1: 685 | version "3.13.1" 686 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 687 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 688 | dependencies: 689 | argparse "^1.0.7" 690 | esprima "^4.0.0" 691 | 692 | json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: 693 | version "1.0.1" 694 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" 695 | integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= 696 | dependencies: 697 | jsonify "~0.0.0" 698 | 699 | jsonify@~0.0.0: 700 | version "0.0.0" 701 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 702 | integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= 703 | 704 | jsonpointer@^4.0.0: 705 | version "4.0.1" 706 | resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" 707 | integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= 708 | 709 | levn@^0.3.0, levn@~0.3.0: 710 | version "0.3.0" 711 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 712 | integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= 713 | dependencies: 714 | prelude-ls "~1.1.2" 715 | type-check "~0.3.2" 716 | 717 | lodash.assign@^4.0.0: 718 | version "4.2.0" 719 | resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" 720 | integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= 721 | 722 | lodash.pickby@^4.0.0: 723 | version "4.6.0" 724 | resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" 725 | integrity sha1-feoh2MGNdwOifHBMFdO4SmfjOv8= 726 | 727 | lodash@^4.0.0, lodash@^4.17.4, lodash@^4.3.0: 728 | version "4.17.15" 729 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" 730 | integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== 731 | 732 | loose-envify@^1.0.0, loose-envify@^1.3.1, loose-envify@^1.4.0: 733 | version "1.4.0" 734 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 735 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 736 | dependencies: 737 | js-tokens "^3.0.0 || ^4.0.0" 738 | 739 | minimatch@^3.0.4: 740 | version "3.0.4" 741 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 742 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 743 | dependencies: 744 | brace-expansion "^1.1.7" 745 | 746 | minimist@0.0.8: 747 | version "0.0.8" 748 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 749 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= 750 | 751 | mkdirp@^0.5.0, mkdirp@^0.5.1: 752 | version "0.5.1" 753 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 754 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= 755 | dependencies: 756 | minimist "0.0.8" 757 | 758 | ms@2.0.0: 759 | version "2.0.0" 760 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 761 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 762 | 763 | mute-stream@0.0.5: 764 | version "0.0.5" 765 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" 766 | integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= 767 | 768 | natural-compare@^1.4.0: 769 | version "1.4.0" 770 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 771 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 772 | 773 | next-tick@^1.0.0: 774 | version "1.0.0" 775 | resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" 776 | integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= 777 | 778 | node-fetch@^1.0.1: 779 | version "1.7.3" 780 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" 781 | integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== 782 | dependencies: 783 | encoding "^0.1.11" 784 | is-stream "^1.0.1" 785 | 786 | number-is-nan@^1.0.0: 787 | version "1.0.1" 788 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 789 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 790 | 791 | object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: 792 | version "4.1.1" 793 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 794 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 795 | 796 | once@^1.3.0: 797 | version "1.4.0" 798 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 799 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 800 | dependencies: 801 | wrappy "1" 802 | 803 | onetime@^1.0.0: 804 | version "1.1.0" 805 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 806 | integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= 807 | 808 | optionator@^0.8.2: 809 | version "0.8.2" 810 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" 811 | integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= 812 | dependencies: 813 | deep-is "~0.1.3" 814 | fast-levenshtein "~2.0.4" 815 | levn "~0.3.0" 816 | prelude-ls "~1.1.2" 817 | type-check "~0.3.2" 818 | wordwrap "~1.0.0" 819 | 820 | os-homedir@^1.0.0: 821 | version "1.0.2" 822 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 823 | integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= 824 | 825 | path-is-absolute@^1.0.0: 826 | version "1.0.1" 827 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 828 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 829 | 830 | path-is-inside@^1.0.1: 831 | version "1.0.2" 832 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 833 | integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= 834 | 835 | path-parse@^1.0.6: 836 | version "1.0.6" 837 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 838 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 839 | 840 | pluralize@^1.2.1: 841 | version "1.2.1" 842 | resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" 843 | integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= 844 | 845 | prelude-ls@~1.1.2: 846 | version "1.1.2" 847 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 848 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 849 | 850 | process-nextick-args@~2.0.0: 851 | version "2.0.1" 852 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 853 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 854 | 855 | progress@^1.1.8: 856 | version "1.1.8" 857 | resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" 858 | integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= 859 | 860 | promise@^7.1.1: 861 | version "7.3.1" 862 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" 863 | integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== 864 | dependencies: 865 | asap "~2.0.3" 866 | 867 | prop-types@*: 868 | version "15.8.1" 869 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" 870 | integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== 871 | dependencies: 872 | loose-envify "^1.4.0" 873 | object-assign "^4.1.1" 874 | react-is "^16.13.1" 875 | 876 | prop-types@^15.6.0: 877 | version "15.7.2" 878 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" 879 | integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== 880 | dependencies: 881 | loose-envify "^1.4.0" 882 | object-assign "^4.1.1" 883 | react-is "^16.8.1" 884 | 885 | react-is@^16.13.1: 886 | version "16.13.1" 887 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" 888 | integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== 889 | 890 | react-is@^16.8.1: 891 | version "16.9.0" 892 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" 893 | integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== 894 | 895 | react-timer-mixin@^0.13.3: 896 | version "0.13.4" 897 | resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3" 898 | integrity sha512-4+ow23tp/Tv7hBM5Az5/Be/eKKF7DIvJ09voz5LyHGQaqqz9WV8YMs31eFvcYQs7d451LSg7kDJV70XYN/Ug/Q== 899 | 900 | readable-stream@^2.2.2: 901 | version "2.3.6" 902 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" 903 | integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== 904 | dependencies: 905 | core-util-is "~1.0.0" 906 | inherits "~2.0.3" 907 | isarray "~1.0.0" 908 | process-nextick-args "~2.0.0" 909 | safe-buffer "~5.1.1" 910 | string_decoder "~1.1.1" 911 | util-deprecate "~1.0.1" 912 | 913 | readline2@^1.0.1: 914 | version "1.0.1" 915 | resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" 916 | integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= 917 | dependencies: 918 | code-point-at "^1.0.0" 919 | is-fullwidth-code-point "^1.0.0" 920 | mute-stream "0.0.5" 921 | 922 | rechoir@^0.6.2: 923 | version "0.6.2" 924 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" 925 | integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= 926 | dependencies: 927 | resolve "^1.1.6" 928 | 929 | regenerator-runtime@^0.11.0: 930 | version "0.11.1" 931 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" 932 | integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== 933 | 934 | require-uncached@^1.0.2: 935 | version "1.0.3" 936 | resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" 937 | integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= 938 | dependencies: 939 | caller-path "^0.1.0" 940 | resolve-from "^1.0.0" 941 | 942 | resolve-from@^1.0.0: 943 | version "1.0.1" 944 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" 945 | integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= 946 | 947 | resolve@^1.1.6: 948 | version "1.12.0" 949 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" 950 | integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== 951 | dependencies: 952 | path-parse "^1.0.6" 953 | 954 | restore-cursor@^1.0.1: 955 | version "1.0.1" 956 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 957 | integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= 958 | dependencies: 959 | exit-hook "^1.0.0" 960 | onetime "^1.0.0" 961 | 962 | rimraf@~2.6.2: 963 | version "2.6.3" 964 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" 965 | integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== 966 | dependencies: 967 | glob "^7.1.3" 968 | 969 | run-async@^0.1.0: 970 | version "0.1.0" 971 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" 972 | integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= 973 | dependencies: 974 | once "^1.3.0" 975 | 976 | rx-lite@^3.1.2: 977 | version "3.1.2" 978 | resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" 979 | integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= 980 | 981 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 982 | version "5.1.2" 983 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 984 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 985 | 986 | "safer-buffer@>= 2.1.2 < 3": 987 | version "2.1.2" 988 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 989 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 990 | 991 | setimmediate@^1.0.5: 992 | version "1.0.5" 993 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 994 | integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= 995 | 996 | shelljs@^0.7.5: 997 | version "0.7.8" 998 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" 999 | integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= 1000 | dependencies: 1001 | glob "^7.0.0" 1002 | interpret "^1.0.0" 1003 | rechoir "^0.6.2" 1004 | 1005 | slice-ansi@0.0.4: 1006 | version "0.0.4" 1007 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" 1008 | integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= 1009 | 1010 | sprintf-js@~1.0.2: 1011 | version "1.0.3" 1012 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1013 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 1014 | 1015 | string-width@^1.0.1: 1016 | version "1.0.2" 1017 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1018 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 1019 | dependencies: 1020 | code-point-at "^1.0.0" 1021 | is-fullwidth-code-point "^1.0.0" 1022 | strip-ansi "^3.0.0" 1023 | 1024 | string-width@^2.0.0: 1025 | version "2.1.1" 1026 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1027 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 1028 | dependencies: 1029 | is-fullwidth-code-point "^2.0.0" 1030 | strip-ansi "^4.0.0" 1031 | 1032 | string_decoder@~1.1.1: 1033 | version "1.1.1" 1034 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 1035 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 1036 | dependencies: 1037 | safe-buffer "~5.1.0" 1038 | 1039 | strip-ansi@^3.0.0: 1040 | version "3.0.1" 1041 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1042 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 1043 | dependencies: 1044 | ansi-regex "^2.0.0" 1045 | 1046 | strip-ansi@^4.0.0: 1047 | version "4.0.0" 1048 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1049 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 1050 | dependencies: 1051 | ansi-regex "^3.0.0" 1052 | 1053 | strip-bom@^3.0.0: 1054 | version "3.0.0" 1055 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 1056 | integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= 1057 | 1058 | strip-json-comments@~2.0.1: 1059 | version "2.0.1" 1060 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1061 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 1062 | 1063 | supports-color@^2.0.0: 1064 | version "2.0.0" 1065 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1066 | integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= 1067 | 1068 | table@^3.7.8: 1069 | version "3.8.3" 1070 | resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" 1071 | integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= 1072 | dependencies: 1073 | ajv "^4.7.0" 1074 | ajv-keywords "^1.0.0" 1075 | chalk "^1.1.1" 1076 | lodash "^4.0.0" 1077 | slice-ansi "0.0.4" 1078 | string-width "^2.0.0" 1079 | 1080 | text-table@~0.2.0: 1081 | version "0.2.0" 1082 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1083 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 1084 | 1085 | through@^2.3.6: 1086 | version "2.3.8" 1087 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1088 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 1089 | 1090 | to-fast-properties@^1.0.3: 1091 | version "1.0.3" 1092 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" 1093 | integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= 1094 | 1095 | type-check@~0.3.2: 1096 | version "0.3.2" 1097 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 1098 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 1099 | dependencies: 1100 | prelude-ls "~1.1.2" 1101 | 1102 | type@^1.0.1: 1103 | version "1.2.0" 1104 | resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" 1105 | integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== 1106 | 1107 | typedarray@^0.0.6: 1108 | version "0.0.6" 1109 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1110 | integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= 1111 | 1112 | ua-parser-js@^0.7.18: 1113 | version "0.7.20" 1114 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" 1115 | integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw== 1116 | 1117 | user-home@^2.0.0: 1118 | version "2.0.0" 1119 | resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" 1120 | integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= 1121 | dependencies: 1122 | os-homedir "^1.0.0" 1123 | 1124 | util-deprecate@~1.0.1: 1125 | version "1.0.2" 1126 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1127 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 1128 | 1129 | whatwg-fetch@>=0.10.0: 1130 | version "3.0.0" 1131 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" 1132 | integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== 1133 | 1134 | wordwrap@~1.0.0: 1135 | version "1.0.0" 1136 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 1137 | integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= 1138 | 1139 | wrappy@1: 1140 | version "1.0.2" 1141 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1142 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1143 | 1144 | write@^0.2.1: 1145 | version "0.2.1" 1146 | resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" 1147 | integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= 1148 | dependencies: 1149 | mkdirp "^0.5.1" 1150 | 1151 | xtend@^4.0.0: 1152 | version "4.0.2" 1153 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 1154 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 1155 | --------------------------------------------------------------------------------