├── .eslintignore ├── .gitignore ├── ErrorOverlay.js ├── Examples └── StarterTemplate │ ├── .babelrc │ ├── .gitignore │ ├── Navigation │ ├── BackButton.js │ └── ExRouter.js │ ├── Screens │ ├── DetailScreen.js │ └── ListScreen.js │ ├── assets │ └── icons │ │ ├── app-icon.png │ │ ├── loading-icon.png │ │ └── notification-icon.png │ ├── exp.json │ ├── fetchWithTimeout.js │ ├── main.js │ ├── package.json │ └── yarn.lock ├── LoadingContainer.js ├── LoadingOverlay.js ├── README.md ├── package.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | Examples 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .expo/**/* 2 | node_modules/**/* 3 | -------------------------------------------------------------------------------- /ErrorOverlay.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { 4 | Image, 5 | StyleSheet, 6 | Text, 7 | TouchableOpacity, 8 | } from 'react-native'; 9 | 10 | // todo(brentvatne): set some base64 image as default 11 | let NO_NETWORK_IMAGE_URI = ''; 12 | 13 | export default class ErrorOverlay extends React.Component { 14 | 15 | static propTypes = { 16 | onRetryLoad: PropTypes.func.isRequired, 17 | }; 18 | 19 | constructor(props, context) { 20 | super(props, context); 21 | this.state = { overlayHidden: true }; 22 | } 23 | 24 | hideOverlay() { 25 | this.setState({ overlayHidden: true }); 26 | } 27 | 28 | showOverlay() { 29 | this.setState({ overlayHidden: false }); 30 | } 31 | 32 | render() { 33 | if (this.state.overlayHidden) { 34 | return null; 35 | } 36 | 37 | // 41 | 42 | return ( 43 | 44 | 45 | Unable to contact server. Tap to retry. 46 | 47 | 48 | ); 49 | } 50 | } 51 | 52 | 53 | let styles = StyleSheet.create({ 54 | overlay: { 55 | backgroundColor: '#fff', 56 | position: 'absolute', 57 | top: 0, 58 | bottom: 0, 59 | left: 0, 60 | right: 0, 61 | justifyContent: 'center', 62 | alignItems: 'center', 63 | }, 64 | }); 65 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["babel-preset-expo"], 3 | "env": { 4 | "development": { 5 | "plugins": ["transform-react-jsx-source"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/.gitignore: -------------------------------------------------------------------------------- 1 | .expo 2 | node_modules/**/* 3 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/Navigation/BackButton.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-present 650 Industries. All rights reserved. 3 | * 4 | * @providesModule BackButton 5 | */ 6 | 'use strict'; 7 | 8 | import React, { PropTypes } from 'react'; 9 | import { 10 | StyleSheet, 11 | PixelRatio, 12 | TouchableOpacity, 13 | } from 'react-native'; 14 | 15 | import ExNavigator from '@expo/react-native-navigator'; 16 | import ResponsiveImage from '@expo/react-native-responsive-image'; 17 | 18 | export default class BackButton extends React.Component { 19 | static propTypes = { 20 | navigator: PropTypes.object.isRequired, 21 | }; 22 | 23 | render() { 24 | return ( 25 | this.props.navigator.pop()} 28 | style={ExNavigator.Styles.barBackButton}> 29 | 23 | ); 24 | }, 25 | }; 26 | 27 | const ExRouter = { 28 | getHomeRoute() { 29 | return { 30 | ...baseRoute, 31 | 32 | getTitle() { 33 | return '/r/reactnative'; 34 | }, 35 | 36 | renderTitle() { 37 | return renderTitle(this); 38 | }, 39 | 40 | getSceneClass() { 41 | return require('ListScreen').default; 42 | }, 43 | }; 44 | }, 45 | 46 | getDetailRoute(url) { 47 | return { 48 | ...baseRoute, 49 | 50 | renderScene(navigator) { 51 | let DetailScreen = require('DetailScreen').default; 52 | return ( 53 | 57 | ); 58 | } 59 | }; 60 | }, 61 | }; 62 | 63 | let titleContainerStyle = { 64 | position: 'absolute', 65 | top: 0, 66 | left: 0, 67 | bottom: 0, 68 | right: 0, 69 | alignItems: 'center', 70 | }; 71 | 72 | if (Platform.OS === 'android') { 73 | titleContainerStyle.right = 72; 74 | } 75 | 76 | let titleTextStyle = { 77 | color: '#fff', 78 | fontSize: Platform.OS === 'ios' ? 15 : 18, 79 | fontWeight: 'bold', 80 | marginTop: 13, 81 | }; 82 | 83 | 84 | function renderTitle(route) { 85 | return ( 86 | 87 | {route.getTitle()} 88 | 89 | ); 90 | } 91 | 92 | export default ExRouter; 93 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/Screens/DetailScreen.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-present 650 Industries. All rights reserved. 3 | * 4 | * @providesModule DetailScreen 5 | */ 6 | 'use strict'; 7 | 8 | import React, { PropTypes } from 'react'; 9 | import { 10 | ListView, 11 | Platform, 12 | StyleSheet, 13 | Text, 14 | View, 15 | } from 'react-native'; 16 | 17 | import LoadingContainer from 'react-native-loading-container'; 18 | import fetchWithTimeout from 'fetchWithTimeout' 19 | 20 | const IS_NESTED_COMMENT = 'this-is-a-nested-comment'; 21 | 22 | export default class DetailScreen extends React.Component { 23 | 24 | static propTypes = { 25 | url: PropTypes.string.isRequired, 26 | } 27 | 28 | constructor(props) { 29 | super(props); 30 | 31 | this._loadInitialDataAsync = this._loadInitialDataAsync.bind(this); 32 | this._onReadyAsync = this._onReadyAsync.bind(this); 33 | this._renderRow = this._renderRow.bind(this); 34 | 35 | let dataSource = new ListView.DataSource({ 36 | rowHasChanged: (r1, r2) => r1 !== r2, 37 | }); 38 | 39 | this.state = { 40 | dataSource, 41 | story: null, 42 | }; 43 | } 44 | 45 | render() { 46 | return ( 47 | 50 | 51 | {this._renderStory()} 52 | {this._renderNoComments()} 53 | 58 | 59 | 60 | ); 61 | } 62 | 63 | _renderStory() { 64 | let { story } = this.state; 65 | 66 | if (!story) { 67 | return; 68 | } 69 | 70 | return ( 71 | 72 | 73 | {story.title} 74 | 75 | 76 | {story.author} 77 | 78 | 79 | ); 80 | } 81 | 82 | _renderNoComments() { 83 | let { story, dataSource } = this.state; 84 | 85 | if (!story || dataSource.getRowCount() > 0) { 86 | return; 87 | } 88 | 89 | return ( 90 | 91 | 92 | No comments on this post yet 93 | 94 | 95 | ); 96 | } 97 | 98 | async _loadInitialDataAsync() { 99 | let response = await fetchWithTimeout(`https://www.reddit.com/${this.props.url}.json`); 100 | return response.json(); 101 | } 102 | 103 | async _onReadyAsync([{data: {children: [{data: story}]}}, {data: {children: comments}}]) { 104 | let dataSource = this.state.dataSource.cloneWithRows(comments); 105 | 106 | return new Promise((resolve) => { 107 | this.setState({story, dataSource}, resolve); 108 | }); 109 | } 110 | 111 | _renderRow({data}, additionalInfo) { 112 | let replies; 113 | 114 | if (data.replies !== '') { 115 | replies = data.replies.data.children; 116 | } 117 | 118 | return ( 119 | 123 | {data.author} 124 | {data.body} 125 | { replies && 126 | replies.map(row => this._renderRow(row, IS_NESTED_COMMENT)) } 127 | 128 | ); 129 | } 130 | 131 | } 132 | 133 | const styles = StyleSheet.create({ 134 | container: { 135 | marginTop: Platform.OS === 'ios' ? 64 : 60, 136 | flex: 1, 137 | }, 138 | storyTitleText: { 139 | fontSize: 18, 140 | }, 141 | storyAuthorText: { 142 | color: '#888', 143 | }, 144 | storyContainer: { 145 | paddingHorizontal: 5, 146 | paddingVertical: 15, 147 | paddingTop: 10, 148 | margin: 5, 149 | borderBottomWidth: 1, 150 | borderBottomColor: 'rgba(0,0,0,0.05)', 151 | }, 152 | commentContainer: { 153 | margin: 10, 154 | }, 155 | commentAuthorText: { 156 | fontSize: 14, 157 | color: '#888', 158 | }, 159 | nestedCommentContainer: { 160 | backgroundColor: '#f9f9f9', 161 | padding: 10, 162 | marginBottom: 0, 163 | marginTop: 15, 164 | }, 165 | commentBodyText: { 166 | marginTop: 3, 167 | }, 168 | noCommentsContainer: { 169 | flex: 1, 170 | alignItems: 'center', 171 | paddingTop: 50, 172 | }, 173 | noCommentsText: { 174 | color: '#888', 175 | }, 176 | }); 177 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/Screens/ListScreen.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-present 650 Industries. All rights reserved. 3 | * 4 | * @providesModule ListScreen 5 | */ 6 | 'use strict'; 7 | 8 | import React from 'react'; 9 | import { 10 | Image, 11 | ListView, 12 | Platform, 13 | StyleSheet, 14 | Text, 15 | TouchableHighlight, 16 | View, 17 | } from 'react-native'; 18 | 19 | import ExRouter from 'ExRouter'; 20 | import LoadingContainer from 'react-native-loading-container'; 21 | import fetchWithTimeout from 'fetchWithTimeout' 22 | 23 | const SELF_IMAGE = "https://s3-us-west-2.amazonaws.com/examples-exp/reddit/self.png"; 24 | const DEFAULT_IMAGE = "https://s3-us-west-2.amazonaws.com/examples-exp/reddit/default.png"; 25 | 26 | function getImageUri(thumbnail) { 27 | if (thumbnail.match('http:')) { 28 | return { uri: thumbnail }; 29 | } else if (thumbnail === 'self') { 30 | return { uri: SELF_IMAGE }; 31 | } else { 32 | return { uri: DEFAULT_IMAGE }; 33 | } 34 | } 35 | 36 | export default class ListScreen extends React.Component { 37 | 38 | constructor(props) { 39 | super(props); 40 | 41 | this._loadInitialDataAsync = this._loadInitialDataAsync.bind(this); 42 | this._onReadyAsync = this._onReadyAsync.bind(this); 43 | this._renderRow = this._renderRow.bind(this); 44 | 45 | let dataSource = new ListView.DataSource({ 46 | rowHasChanged: (r1, r2) => r1 !== r2, 47 | }); 48 | 49 | this.state = { 50 | dataSource, 51 | }; 52 | } 53 | 54 | render() { 55 | return ( 56 | 59 | 63 | 64 | ); 65 | } 66 | 67 | _renderRow({data}, rowId) { 68 | return ( 69 | { this._handlePress(data) }} 71 | underlayColor='rgba(0,0,0,0.03)'> 72 | 73 | 74 | 75 | 76 | {data.title} 77 | Submitted by {data.author} 78 | {data.num_comments} {parseInt(data.num_comments, 10) === 1 ? 'comment' : 'comments'} 79 | 80 | 81 | 82 | ); 83 | } 84 | 85 | _handlePress({permalink}) { 86 | this.props.navigator.push(ExRouter.getDetailRoute(permalink)); 87 | } 88 | 89 | async _loadInitialDataAsync() { 90 | let response = await fetchWithTimeout('https://www.reddit.com/r/reactnative.json'); 91 | return response.json(); 92 | } 93 | 94 | async _onReadyAsync({data: {children: stories}}) { 95 | let dataSource = this.state.dataSource.cloneWithRows(stories); 96 | 97 | return new Promise((resolve) => { 98 | this.setState({dataSource}, resolve); 99 | }); 100 | } 101 | } 102 | 103 | const styles = StyleSheet.create({ 104 | container: { 105 | marginTop: Platform.OS === 'ios' ? 64 : 60, 106 | }, 107 | row: { 108 | flexDirection: 'row', 109 | paddingTop: 15, 110 | paddingBottom: 10, 111 | borderBottomWidth: 1, 112 | borderBottomColor: 'rgba(0,0,0,0.05)', 113 | }, 114 | rowInfo: { 115 | flexDirection: 'column', 116 | paddingRight: 20, 117 | paddingLeft: 10, 118 | flexWrap: 'wrap', 119 | flex: 1, 120 | }, 121 | titleText: { 122 | fontSize: 17, 123 | color: '#05a5d1', 124 | }, 125 | authorText: { 126 | color: '#888', 127 | fontSize: 14, 128 | marginTop: 5, 129 | }, 130 | commentText: { 131 | color: '#888', 132 | fontSize: 14, 133 | }, 134 | thumbnail: { 135 | width: 70, 136 | height: 52.5, 137 | marginLeft: 5, 138 | }, 139 | }); 140 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/assets/icons/app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expo/react-native-loading-container/addf637539f580fd78f1138be1851928a1951f0b/Examples/StarterTemplate/assets/icons/app-icon.png -------------------------------------------------------------------------------- /Examples/StarterTemplate/assets/icons/loading-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expo/react-native-loading-container/addf637539f580fd78f1138be1851928a1951f0b/Examples/StarterTemplate/assets/icons/loading-icon.png -------------------------------------------------------------------------------- /Examples/StarterTemplate/assets/icons/notification-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expo/react-native-loading-container/addf637539f580fd78f1138be1851928a1951f0b/Examples/StarterTemplate/assets/icons/notification-icon.png -------------------------------------------------------------------------------- /Examples/StarterTemplate/exp.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Example Project for LoadingContainer", 3 | "description": "", 4 | "slug": "react-native-loading-container-example", 5 | "privacy": "public", 6 | "sdkVersion": "16.0.0", 7 | "version": "1.0.0", 8 | "orientation": "portrait", 9 | "primaryColor": "#cccccc", 10 | "icon": "./assets/icons/app-icon.png", 11 | "notification": { 12 | "icon": "./assets/icons/notification-icon.png", 13 | "color": "#000000" 14 | }, 15 | "loading": { 16 | "icon": "./assets/icons/loading-icon.png", 17 | "hideExponentText": false 18 | }, 19 | "packagerOpts": { 20 | "assetExts": ["ttf"] 21 | }, 22 | "ios": { 23 | "supportsTablet": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/fetchWithTimeout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-present 650 Industries. All rights reserved. 3 | * 4 | * @providesModule fetchWithTimeout 5 | */ 6 | 'use strict'; 7 | 8 | function timeoutAsync(promise, ms) { 9 | return new Promise((resolve, reject) => { 10 | let _timer = setTimeout(() => { 11 | reject(new Error('API timeout')); 12 | }, ms); 13 | 14 | promise.then((result) => { 15 | clearTimeout(_timer); 16 | return resolve(result); 17 | }, reject); 18 | }); 19 | } 20 | 21 | export default function fetchWithTimeout(url, options = {}, timeout = 10000) { 22 | return timeoutAsync(fetch(url, options), timeout); 23 | } 24 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/main.js: -------------------------------------------------------------------------------- 1 | import Expo from 'expo'; 2 | import React from 'react'; 3 | import { 4 | BackAndroid, 5 | Platform, 6 | StatusBar, 7 | StyleSheet, 8 | Navigator, 9 | View, 10 | } from 'react-native'; 11 | 12 | import ExNavigator from '@expo/react-native-navigator'; 13 | import ExRouter from 'ExRouter'; 14 | 15 | console.ignoreYellowBox = true; 16 | 17 | class Main extends React.Component { 18 | 19 | componentDidMount() { 20 | if (StatusBar) { 21 | StatusBar.setBarStyle('light-content'); 22 | } 23 | 24 | if (BackAndroid) { 25 | BackAndroid.addEventListener('hardwareBackPress', () => { 26 | if (this._navigator.getCurrentRoutes().length > 1) { 27 | this._navigator.pop(); 28 | return true; 29 | } 30 | 31 | return false; 32 | }); 33 | } 34 | } 35 | 36 | render() { 37 | let initialRoute = ExRouter.getHomeRoute(); 38 | 39 | return ( 40 | 41 | 42 | this._navigator = component} 44 | initialRoute={initialRoute} 45 | renderNavigationBar={props => } 46 | /> 47 | 48 | ); 49 | } 50 | } 51 | 52 | let styles = StyleSheet.create({ 53 | container: { 54 | flex: 1, 55 | backgroundColor: '#fff', 56 | }, 57 | navigationBar: { 58 | backgroundColor: '#05a5d1', 59 | }, 60 | spacer: { 61 | height: Platform.OS === 'android' ? 30 : 0, 62 | backgroundColor: '#05a5d1', 63 | }, 64 | }); 65 | 66 | Expo.registerRootComponent(Main); 67 | -------------------------------------------------------------------------------- /Examples/StarterTemplate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "StarterTemplate", 3 | "version": "1.0.0", 4 | "description": "Hello!", 5 | "main": "main.js", 6 | "author": "brentvatne@gmail.com", 7 | "dependencies": { 8 | "@expo/react-native-navigator": "^0.4.10", 9 | "@expo/react-native-responsive-image": "^1.2.1", 10 | "expo": "^16.0.0", 11 | "react": "16.0.0-alpha.6", 12 | "react-mixin": "^3.0.3", 13 | "react-native": "https://github.com/exponent/react-native/archive/sdk-16.0.0.tar.gz", 14 | "react-native-loading-container": "file:../..", 15 | "react-native-timer-mixin": "^0.11.0" 16 | }, 17 | "exp": { 18 | "name": "/r/reactnative", 19 | "primaryColor": "#00A4D3", 20 | "iconUrl": "https://s3-us-west-2.amazonaws.com/examples-exp/reddit/icon.png" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LoadingContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | } from 'react-native'; 6 | import ReactMixin from 'react-mixin'; 7 | import TimerMixin from 'react-native-timer-mixin'; 8 | import PropTypes from 'prop-types'; 9 | 10 | import cloneReferencedElement from 'react-clone-referenced-element'; 11 | 12 | import LoadingOverlay from './LoadingOverlay'; 13 | import ErrorOverlay from './ErrorOverlay'; 14 | 15 | export default class LoadingContainer extends React.Component { 16 | 17 | static LoadingOverlay = LoadingOverlay; 18 | static ErrorOverlay = ErrorOverlay; 19 | 20 | static propTypes = { 21 | onLoadStartAsync: PropTypes.func.isRequired, 22 | onReadyAsync: PropTypes.func.isRequired, 23 | onError: PropTypes.func, 24 | renderLoadingOverlay: PropTypes.func.isRequired, 25 | renderErrorOverlay: PropTypes.func.isRequired, 26 | }; 27 | 28 | static defaultProps = { 29 | onReadyAsync: () => Promise.resolve(), 30 | renderLoadingOverlay: props => , 31 | renderErrorOverlay: props => , 32 | }; 33 | 34 | 35 | state = { 36 | isLoading: false, 37 | }; 38 | 39 | componentDidMount() { 40 | this._attemptLoadAsync().done(); 41 | } 42 | 43 | render() { 44 | let loadingOverlay = cloneReferencedElement( 45 | this.props.renderLoadingOverlay({}), 46 | { ref: component => { this._loadingOverlay = component; } } 47 | ); 48 | 49 | let errorOverlay = cloneReferencedElement( 50 | this.props.renderErrorOverlay({onRetryLoad: this._attemptLoadAsync}), 51 | { ref: component => { this._errorOverlay = component; } } 52 | ); 53 | 54 | return ( 55 | 56 | {this.props.children} 57 | {loadingOverlay} 58 | {errorOverlay} 59 | 60 | ); 61 | } 62 | 63 | 64 | showLoadingOverlay = () => { 65 | this._errorOverlay.hideOverlay(); 66 | this._loadingOverlay.showOverlay(); 67 | } 68 | 69 | reloadAsync = async () => { 70 | return this._attemptLoadAsync(); 71 | } 72 | 73 | _attemptLoadAsync = async () => { 74 | if (this.state.isLoading) { 75 | return; 76 | } 77 | 78 | this.setState({ isLoading: true }); 79 | this.showLoadingOverlay(); 80 | let result; 81 | 82 | try { 83 | result = await this.props.onLoadStartAsync(); 84 | } catch (e) { 85 | this._handleError(e); 86 | return; 87 | } 88 | 89 | await this.props.onReadyAsync(result); 90 | this._loadingOverlay && this._loadingOverlay.fadeOverlay(); 91 | this.setState({ isLoading: false }); 92 | } 93 | 94 | _handleError = (e) => { 95 | this.setState({ isLoading: false }); 96 | this._errorOverlay && this._errorOverlay.showOverlay(); 97 | this._loadingOverlay && this._loadingOverlay.hideOverlay(); 98 | if (this.props.onError) { 99 | this.props.onError(e); 100 | } 101 | } 102 | } 103 | 104 | ReactMixin(LoadingContainer.prototype, TimerMixin); 105 | 106 | const styles = StyleSheet.create({ 107 | container: { 108 | position: 'absolute', 109 | top: 0, 110 | bottom: 0, 111 | left: 0, 112 | right: 0, 113 | }, 114 | }); 115 | -------------------------------------------------------------------------------- /LoadingOverlay.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Animated, 4 | Easing, 5 | StyleSheet, 6 | View, 7 | ActivityIndicator, 8 | } from 'react-native'; 9 | 10 | const FADE_DELAY_MS = 85; 11 | 12 | export default class LoadingOverlay extends React.Component { 13 | state = { 14 | overlayHidden: false, 15 | overlayOpacity: new Animated.Value(1), 16 | }; 17 | 18 | fadeOverlay() { 19 | Animated.sequence([ 20 | Animated.delay(FADE_DELAY_MS), 21 | Animated.timing(this.state.overlayOpacity, { 22 | toValue: 0, 23 | easing: Easing.in(Easing.linear), 24 | duration: 250, 25 | }), 26 | ]).start(result => { 27 | if (result.finished) { 28 | this.setState({ overlayHidden: true }); 29 | } 30 | }); 31 | } 32 | 33 | hideOverlay() { 34 | this.setState({ overlayHidden: true }); 35 | } 36 | 37 | showOverlay() { 38 | this.state.overlayOpacity.setValue(1); 39 | this.setState({ overlayHidden: false }); 40 | } 41 | 42 | render() { 43 | if (this.state.overlayHidden) { 44 | return null; 45 | } 46 | 47 | let opacityStyle = { 48 | opacity: this.state.overlayOpacity, 49 | }; 50 | 51 | return ( 52 | 56 | { 57 | React.Children.count(this.props.children) > 0 ? 58 | this.props.children : 59 | 60 | } 61 | 62 | ); 63 | } 64 | } 65 | 66 | let styles = StyleSheet.create({ 67 | overlay: { 68 | backgroundColor: '#fff', 69 | position: 'absolute', 70 | top: 0, 71 | bottom: 0, 72 | left: 0, 73 | right: 0, 74 | justifyContent: 'center', 75 | alignItems: 'center', 76 | }, 77 | }); 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LoadingContainer [![Slack](http://slack.expo.io/badge.svg)](http://slack.expo.io) 2 | 3 | LoadingContainer is a component that co-ordinates fetching data, displaying a loading indicator while that's in progress, and an error message with a retry button when a request fails. 4 | 5 | ## Why? 6 | 7 | We are building an app where pretty much every screen has to fetch new data, so we wanted a way to generalize our logic for showing loading screens, handling errors and retries. 8 | 9 | ## Installation 10 | 11 | ``` 12 | npm install react-native-loading-container --save 13 | ``` 14 | 15 | LoadingContainer is compatible with React Native 0.15 and newer. 16 | 17 | ## Usage 18 | 19 | Import LoadingContainer as a JavaScript module: 20 | 21 | ```js 22 | import LoadingContainer from 'react-native-loading-container'; 23 | ``` 24 | 25 | The only two props that are required are `onLoadStartAsync` and `onReadyAsync` - these must both be async functions (or return Promises), and must resolve when they are completed. 26 | 27 | `onLoadStartAsync` is responsible for fetching the data that the scene needs to render and returning it. In the example below, we return the JSON response from the reactnative subreddit. If an exception is thrown in this function, an error overlay is rendered where the user can tap to retry. Tapping retry will invoke this function again. The return value of `onLoadStartAsync` is fed into `_onReadyAsync`. 28 | 29 | `onReadyAsync` is responsible for taking the data fetched by `onLoadStartAsync` and updating our component state. When it resolves, LoadingContainer will hide the loading indicator. 30 | 31 | 32 | ```js 33 | export default class ListScreen extends React.Component { 34 | 35 | render() { 36 | return ( 37 | 40 | { /* render content */ } 41 | 42 | ); 43 | } 44 | 45 | async _loadInitialDataAsync() { 46 | let response = await fetchWithTimeout('https://www.reddit.com/r/reactnative.json'); 47 | return response.json(); 48 | } 49 | 50 | async _onReadyAsync({data: {children: stories}}) { 51 | return new Promise((resolve) => { 52 | this.setState({stories}, resolve); 53 | }); 54 | } 55 | 56 | } 57 | ``` 58 | 59 | A complete, runnable example is available in [Examples/StarterTemplate](https://github.com/expo/react-native-loading-container/tree/master/Examples/StarterTemplate). 60 | 61 | LoadingContainer can be used anywhere, but is especially well-suited to wrapping the content of your scene components. A scene component is the top-level component for each route. 62 | 63 | 64 | ### Customization 65 | 66 | LoadingContainer was built to our specific use case so it might not have all of the hooks that you will want to customize it for your application -- if this is the case, please submit a pull request. 67 | 68 | Currently only the following props are exposed: 69 | 70 | - `onError` - invoked with the exception object when `onLoadStartAsync` throws an exception. 71 | - `renderLoadingOverlay` - returns a React element that will be rendered when loading is in progress. It must implement `showOverlay`, `hideOverlay` and `fadeOverlay` methods. 72 | - `renderErrorOverlay` - returns a React element that will be rendered when error occurs. It will receive a function prop called `onRetryLoad` that should be invoked when the user indicates that they would like retry fetching data. 73 | 74 | ```js 75 | console.log(e)} 77 | renderLoadingOverlay={props => } 78 | renderErrorOverlay={props => } 79 | /> 80 | ``` 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-loading-container", 3 | "version": "0.5.0", 4 | "description": "", 5 | "main": "LoadingContainer.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/expo/react-native-loading-container.git" 12 | }, 13 | "author": "", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/expo/react-native-loading-container/issues" 17 | }, 18 | "homepage": "https://github.com/expo/react-native-loading-container#readme", 19 | "dependencies": { 20 | "prop-types": "^15.5.8", 21 | "react-clone-referenced-element": "^1.0.1", 22 | "react-mixin": "^3.0.3", 23 | "react-native-timer-mixin": "^0.11.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | acorn-to-esprima@^2.0.4: 6 | version "2.0.8" 7 | resolved "https://registry.yarnpkg.com/acorn-to-esprima/-/acorn-to-esprima-2.0.8.tgz#003f0c642eb92132f417d3708f14ada82adf2eb1" 8 | 9 | align-text@^0.1.1, align-text@^0.1.3: 10 | version "0.1.4" 11 | resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" 12 | dependencies: 13 | kind-of "^3.0.2" 14 | longest "^1.0.1" 15 | repeat-string "^1.5.2" 16 | 17 | amdefine@>=0.0.4: 18 | version "1.0.1" 19 | resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" 20 | 21 | ansi-escapes@^1.1.0: 22 | version "1.4.0" 23 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 24 | 25 | ansi-regex@^2.0.0: 26 | version "2.1.1" 27 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 28 | 29 | ansi-styles@^2.2.1: 30 | version "2.2.1" 31 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 32 | 33 | argparse@^1.0.2: 34 | version "1.0.9" 35 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" 36 | dependencies: 37 | sprintf-js "~1.0.2" 38 | 39 | array-union@^1.0.1: 40 | version "1.0.2" 41 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 42 | dependencies: 43 | array-uniq "^1.0.1" 44 | 45 | array-uniq@^1.0.1: 46 | version "1.0.3" 47 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 48 | 49 | arrify@^1.0.0: 50 | version "1.0.1" 51 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 52 | 53 | asap@~2.0.3: 54 | version "2.0.5" 55 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" 56 | 57 | async@^1.4.0: 58 | version "1.5.2" 59 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 60 | 61 | babel-code-frame@^6.22.0: 62 | version "6.22.0" 63 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" 64 | dependencies: 65 | chalk "^1.1.0" 66 | esutils "^2.0.2" 67 | js-tokens "^3.0.0" 68 | 69 | babel-eslint@^5.0.0-beta6: 70 | version "5.0.4" 71 | resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-5.0.4.tgz#a6ba51ae582a1d4e25adfddbc2a61f8d5a9040b9" 72 | dependencies: 73 | acorn-to-esprima "^2.0.4" 74 | babel-traverse "^6.0.20" 75 | babel-types "^6.0.19" 76 | babylon "^6.0.18" 77 | lodash.assign "^3.2.0" 78 | lodash.pick "^3.1.0" 79 | 80 | babel-messages@^6.23.0: 81 | version "6.23.0" 82 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" 83 | dependencies: 84 | babel-runtime "^6.22.0" 85 | 86 | babel-runtime@^6.22.0: 87 | version "6.23.0" 88 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" 89 | dependencies: 90 | core-js "^2.4.0" 91 | regenerator-runtime "^0.10.0" 92 | 93 | babel-traverse@^6.0.20: 94 | version "6.24.1" 95 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695" 96 | dependencies: 97 | babel-code-frame "^6.22.0" 98 | babel-messages "^6.23.0" 99 | babel-runtime "^6.22.0" 100 | babel-types "^6.24.1" 101 | babylon "^6.15.0" 102 | debug "^2.2.0" 103 | globals "^9.0.0" 104 | invariant "^2.2.0" 105 | lodash "^4.2.0" 106 | 107 | babel-types@^6.0.19, babel-types@^6.24.1: 108 | version "6.24.1" 109 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975" 110 | dependencies: 111 | babel-runtime "^6.22.0" 112 | esutils "^2.0.2" 113 | lodash "^4.2.0" 114 | to-fast-properties "^1.0.1" 115 | 116 | babylon@^6.0.18, babylon@^6.15.0: 117 | version "6.17.0" 118 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.0.tgz#37da948878488b9c4e3c4038893fa3314b3fc932" 119 | 120 | balanced-match@^0.4.1: 121 | version "0.4.2" 122 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" 123 | 124 | brace-expansion@^1.0.0: 125 | version "1.1.7" 126 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" 127 | dependencies: 128 | balanced-match "^0.4.1" 129 | concat-map "0.0.1" 130 | 131 | buffer-shims@~1.0.0: 132 | version "1.0.0" 133 | resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" 134 | 135 | camelcase@^1.0.2: 136 | version "1.2.1" 137 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" 138 | 139 | center-align@^0.1.1: 140 | version "0.1.3" 141 | resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" 142 | dependencies: 143 | align-text "^0.1.3" 144 | lazy-cache "^1.0.3" 145 | 146 | chalk@^1.0.0, chalk@^1.1.0: 147 | version "1.1.3" 148 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 149 | dependencies: 150 | ansi-styles "^2.2.1" 151 | escape-string-regexp "^1.0.2" 152 | has-ansi "^2.0.0" 153 | strip-ansi "^3.0.0" 154 | supports-color "^2.0.0" 155 | 156 | circular-json@^0.3.1: 157 | version "0.3.1" 158 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" 159 | 160 | cli-cursor@^1.0.1: 161 | version "1.0.2" 162 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 163 | dependencies: 164 | restore-cursor "^1.0.1" 165 | 166 | cli-width@^1.0.1: 167 | version "1.1.1" 168 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d" 169 | 170 | cliui@^2.1.0: 171 | version "2.1.0" 172 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" 173 | dependencies: 174 | center-align "^0.1.1" 175 | right-align "^0.1.1" 176 | wordwrap "0.0.2" 177 | 178 | code-point-at@^1.0.0: 179 | version "1.1.0" 180 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 181 | 182 | concat-map@0.0.1: 183 | version "0.0.1" 184 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 185 | 186 | concat-stream@^1.4.6: 187 | version "1.6.0" 188 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" 189 | dependencies: 190 | inherits "^2.0.3" 191 | readable-stream "^2.2.2" 192 | typedarray "^0.0.6" 193 | 194 | core-js@^1.0.0: 195 | version "1.2.7" 196 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" 197 | 198 | core-js@^2.4.0: 199 | version "2.4.1" 200 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" 201 | 202 | core-util-is@~1.0.0: 203 | version "1.0.2" 204 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 205 | 206 | d@1: 207 | version "1.0.0" 208 | resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" 209 | dependencies: 210 | es5-ext "^0.10.9" 211 | 212 | debug@^2.1.1, debug@^2.2.0: 213 | version "2.6.6" 214 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a" 215 | dependencies: 216 | ms "0.7.3" 217 | 218 | decamelize@^1.0.0: 219 | version "1.2.0" 220 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 221 | 222 | deep-is@~0.1.3: 223 | version "0.1.3" 224 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 225 | 226 | del@^2.0.2: 227 | version "2.2.2" 228 | resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" 229 | dependencies: 230 | globby "^5.0.0" 231 | is-path-cwd "^1.0.0" 232 | is-path-in-cwd "^1.0.0" 233 | object-assign "^4.0.1" 234 | pify "^2.0.0" 235 | pinkie-promise "^2.0.0" 236 | rimraf "^2.2.8" 237 | 238 | doctrine@^0.7.1: 239 | version "0.7.2" 240 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" 241 | dependencies: 242 | esutils "^1.1.6" 243 | isarray "0.0.1" 244 | 245 | encoding@^0.1.11: 246 | version "0.1.12" 247 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 248 | dependencies: 249 | iconv-lite "~0.4.13" 250 | 251 | es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: 252 | version "0.10.15" 253 | resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.15.tgz#c330a5934c1ee21284a7c081a86e5fd937c91ea6" 254 | dependencies: 255 | es6-iterator "2" 256 | es6-symbol "~3.1" 257 | 258 | es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: 259 | version "2.0.1" 260 | resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" 261 | dependencies: 262 | d "1" 263 | es5-ext "^0.10.14" 264 | es6-symbol "^3.1" 265 | 266 | es6-map@^0.1.3: 267 | version "0.1.5" 268 | resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" 269 | dependencies: 270 | d "1" 271 | es5-ext "~0.10.14" 272 | es6-iterator "~2.0.1" 273 | es6-set "~0.1.5" 274 | es6-symbol "~3.1.1" 275 | event-emitter "~0.3.5" 276 | 277 | es6-set@~0.1.5: 278 | version "0.1.5" 279 | resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" 280 | dependencies: 281 | d "1" 282 | es5-ext "~0.10.14" 283 | es6-iterator "~2.0.1" 284 | es6-symbol "3.1.1" 285 | event-emitter "~0.3.5" 286 | 287 | es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: 288 | version "3.1.1" 289 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" 290 | dependencies: 291 | d "1" 292 | es5-ext "~0.10.14" 293 | 294 | es6-weak-map@^2.0.1: 295 | version "2.0.2" 296 | resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" 297 | dependencies: 298 | d "1" 299 | es5-ext "^0.10.14" 300 | es6-iterator "^2.0.1" 301 | es6-symbol "^3.1.1" 302 | 303 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 304 | version "1.0.5" 305 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 306 | 307 | escope@^3.3.0: 308 | version "3.6.0" 309 | resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" 310 | dependencies: 311 | es6-map "^0.1.3" 312 | es6-weak-map "^2.0.1" 313 | esrecurse "^4.1.0" 314 | estraverse "^4.1.1" 315 | 316 | eslint-plugin-react@^3.15.0: 317 | version "3.16.1" 318 | resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-3.16.1.tgz#262d96b77d7c4a42af809a73c0e527a58612293c" 319 | 320 | eslint@^1.10.3: 321 | version "1.10.3" 322 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-1.10.3.tgz#fb19a91b13c158082bbca294b17d979bc8353a0a" 323 | dependencies: 324 | chalk "^1.0.0" 325 | concat-stream "^1.4.6" 326 | debug "^2.1.1" 327 | doctrine "^0.7.1" 328 | escape-string-regexp "^1.0.2" 329 | escope "^3.3.0" 330 | espree "^2.2.4" 331 | estraverse "^4.1.1" 332 | estraverse-fb "^1.3.1" 333 | esutils "^2.0.2" 334 | file-entry-cache "^1.1.1" 335 | glob "^5.0.14" 336 | globals "^8.11.0" 337 | handlebars "^4.0.0" 338 | inquirer "^0.11.0" 339 | is-my-json-valid "^2.10.0" 340 | is-resolvable "^1.0.0" 341 | js-yaml "3.4.5" 342 | json-stable-stringify "^1.0.0" 343 | lodash.clonedeep "^3.0.1" 344 | lodash.merge "^3.3.2" 345 | lodash.omit "^3.1.0" 346 | minimatch "^3.0.0" 347 | mkdirp "^0.5.0" 348 | object-assign "^4.0.1" 349 | optionator "^0.6.0" 350 | path-is-absolute "^1.0.0" 351 | path-is-inside "^1.0.1" 352 | shelljs "^0.5.3" 353 | strip-json-comments "~1.0.1" 354 | text-table "~0.2.0" 355 | user-home "^2.0.0" 356 | xml-escape "~1.0.0" 357 | 358 | espree@^2.2.4: 359 | version "2.2.5" 360 | resolved "https://registry.yarnpkg.com/espree/-/espree-2.2.5.tgz#df691b9310889402aeb29cc066708c56690b854b" 361 | 362 | esprima@^2.6.0: 363 | version "2.7.3" 364 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" 365 | 366 | esrecurse@^4.1.0: 367 | version "4.1.0" 368 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" 369 | dependencies: 370 | estraverse "~4.1.0" 371 | object-assign "^4.0.1" 372 | 373 | estraverse-fb@^1.3.1: 374 | version "1.3.1" 375 | resolved "https://registry.yarnpkg.com/estraverse-fb/-/estraverse-fb-1.3.1.tgz#160e75a80e605b08ce894bcce2fe3e429abf92bf" 376 | 377 | estraverse@^4.1.1: 378 | version "4.2.0" 379 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" 380 | 381 | estraverse@~4.1.0: 382 | version "4.1.1" 383 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" 384 | 385 | esutils@^1.1.6: 386 | version "1.1.6" 387 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375" 388 | 389 | esutils@^2.0.2: 390 | version "2.0.2" 391 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 392 | 393 | event-emitter@~0.3.5: 394 | version "0.3.5" 395 | resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" 396 | dependencies: 397 | d "1" 398 | es5-ext "~0.10.14" 399 | 400 | exit-hook@^1.0.0: 401 | version "1.1.1" 402 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 403 | 404 | fast-levenshtein@~1.0.6: 405 | version "1.0.7" 406 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz#0178dcdee023b92905193af0959e8a7639cfdcb9" 407 | 408 | fbjs@^0.8.9: 409 | version "0.8.12" 410 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04" 411 | dependencies: 412 | core-js "^1.0.0" 413 | isomorphic-fetch "^2.1.1" 414 | loose-envify "^1.0.0" 415 | object-assign "^4.1.0" 416 | promise "^7.1.1" 417 | setimmediate "^1.0.5" 418 | ua-parser-js "^0.7.9" 419 | 420 | figures@^1.3.5: 421 | version "1.7.0" 422 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 423 | dependencies: 424 | escape-string-regexp "^1.0.5" 425 | object-assign "^4.1.0" 426 | 427 | file-entry-cache@^1.1.1: 428 | version "1.3.1" 429 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" 430 | dependencies: 431 | flat-cache "^1.2.1" 432 | object-assign "^4.0.1" 433 | 434 | flat-cache@^1.2.1: 435 | version "1.2.2" 436 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" 437 | dependencies: 438 | circular-json "^0.3.1" 439 | del "^2.0.2" 440 | graceful-fs "^4.1.2" 441 | write "^0.2.1" 442 | 443 | fs.realpath@^1.0.0: 444 | version "1.0.0" 445 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 446 | 447 | generate-function@^2.0.0: 448 | version "2.0.0" 449 | resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" 450 | 451 | generate-object-property@^1.1.0: 452 | version "1.2.0" 453 | resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" 454 | dependencies: 455 | is-property "^1.0.0" 456 | 457 | glob@^5.0.14: 458 | version "5.0.15" 459 | resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 460 | dependencies: 461 | inflight "^1.0.4" 462 | inherits "2" 463 | minimatch "2 || 3" 464 | once "^1.3.0" 465 | path-is-absolute "^1.0.0" 466 | 467 | glob@^7.0.3, glob@^7.0.5: 468 | version "7.1.1" 469 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 470 | dependencies: 471 | fs.realpath "^1.0.0" 472 | inflight "^1.0.4" 473 | inherits "2" 474 | minimatch "^3.0.2" 475 | once "^1.3.0" 476 | path-is-absolute "^1.0.0" 477 | 478 | globals@^8.11.0: 479 | version "8.18.0" 480 | resolved "https://registry.yarnpkg.com/globals/-/globals-8.18.0.tgz#93d4a62bdcac38cfafafc47d6b034768cb0ffcb4" 481 | 482 | globals@^9.0.0: 483 | version "9.17.0" 484 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" 485 | 486 | globby@^5.0.0: 487 | version "5.0.0" 488 | resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" 489 | dependencies: 490 | array-union "^1.0.1" 491 | arrify "^1.0.0" 492 | glob "^7.0.3" 493 | object-assign "^4.0.1" 494 | pify "^2.0.0" 495 | pinkie-promise "^2.0.0" 496 | 497 | graceful-fs@^4.1.2: 498 | version "4.1.11" 499 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 500 | 501 | handlebars@^4.0.0: 502 | version "4.0.8" 503 | resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.8.tgz#22b875cd3f0e6cbea30314f144e82bc7a72ff420" 504 | dependencies: 505 | async "^1.4.0" 506 | optimist "^0.6.1" 507 | source-map "^0.4.4" 508 | optionalDependencies: 509 | uglify-js "^2.6" 510 | 511 | has-ansi@^2.0.0: 512 | version "2.0.0" 513 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 514 | dependencies: 515 | ansi-regex "^2.0.0" 516 | 517 | iconv-lite@~0.4.13: 518 | version "0.4.17" 519 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" 520 | 521 | inflight@^1.0.4: 522 | version "1.0.6" 523 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 524 | dependencies: 525 | once "^1.3.0" 526 | wrappy "1" 527 | 528 | inherits@2, inherits@^2.0.3, inherits@~2.0.1: 529 | version "2.0.3" 530 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 531 | 532 | inquirer@^0.11.0: 533 | version "0.11.4" 534 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.11.4.tgz#81e3374e8361beaff2d97016206d359d0b32fa4d" 535 | dependencies: 536 | ansi-escapes "^1.1.0" 537 | ansi-regex "^2.0.0" 538 | chalk "^1.0.0" 539 | cli-cursor "^1.0.1" 540 | cli-width "^1.0.1" 541 | figures "^1.3.5" 542 | lodash "^3.3.1" 543 | readline2 "^1.0.1" 544 | run-async "^0.1.0" 545 | rx-lite "^3.1.2" 546 | string-width "^1.0.1" 547 | strip-ansi "^3.0.0" 548 | through "^2.3.6" 549 | 550 | invariant@^2.2.0: 551 | version "2.2.2" 552 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" 553 | dependencies: 554 | loose-envify "^1.0.0" 555 | 556 | is-buffer@^1.1.5: 557 | version "1.1.5" 558 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" 559 | 560 | is-fullwidth-code-point@^1.0.0: 561 | version "1.0.0" 562 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 563 | dependencies: 564 | number-is-nan "^1.0.0" 565 | 566 | is-my-json-valid@^2.10.0: 567 | version "2.16.0" 568 | resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" 569 | dependencies: 570 | generate-function "^2.0.0" 571 | generate-object-property "^1.1.0" 572 | jsonpointer "^4.0.0" 573 | xtend "^4.0.0" 574 | 575 | is-path-cwd@^1.0.0: 576 | version "1.0.0" 577 | resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" 578 | 579 | is-path-in-cwd@^1.0.0: 580 | version "1.0.0" 581 | resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" 582 | dependencies: 583 | is-path-inside "^1.0.0" 584 | 585 | is-path-inside@^1.0.0: 586 | version "1.0.0" 587 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" 588 | dependencies: 589 | path-is-inside "^1.0.1" 590 | 591 | is-property@^1.0.0: 592 | version "1.0.2" 593 | resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" 594 | 595 | is-resolvable@^1.0.0: 596 | version "1.0.0" 597 | resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" 598 | dependencies: 599 | tryit "^1.0.1" 600 | 601 | is-stream@^1.0.1: 602 | version "1.1.0" 603 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 604 | 605 | isarray@0.0.1: 606 | version "0.0.1" 607 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 608 | 609 | isarray@~1.0.0: 610 | version "1.0.0" 611 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 612 | 613 | isomorphic-fetch@^2.1.1: 614 | version "2.2.1" 615 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 616 | dependencies: 617 | node-fetch "^1.0.1" 618 | whatwg-fetch ">=0.10.0" 619 | 620 | js-tokens@^3.0.0: 621 | version "3.0.1" 622 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" 623 | 624 | js-yaml@3.4.5: 625 | version "3.4.5" 626 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.4.5.tgz#c3403797df12b91866574f2de23646fe8cafb44d" 627 | dependencies: 628 | argparse "^1.0.2" 629 | esprima "^2.6.0" 630 | 631 | json-stable-stringify@^1.0.0: 632 | version "1.0.1" 633 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" 634 | dependencies: 635 | jsonify "~0.0.0" 636 | 637 | jsonify@~0.0.0: 638 | version "0.0.0" 639 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 640 | 641 | jsonpointer@^4.0.0: 642 | version "4.0.1" 643 | resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" 644 | 645 | kind-of@^3.0.2: 646 | version "3.2.0" 647 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.0.tgz#b58abe4d5c044ad33726a8c1525b48cf891bff07" 648 | dependencies: 649 | is-buffer "^1.1.5" 650 | 651 | lazy-cache@^1.0.3: 652 | version "1.0.4" 653 | resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" 654 | 655 | levn@~0.2.5: 656 | version "0.2.5" 657 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.2.5.tgz#ba8d339d0ca4a610e3a3f145b9caf48807155054" 658 | dependencies: 659 | prelude-ls "~1.1.0" 660 | type-check "~0.3.1" 661 | 662 | lodash._arraycopy@^3.0.0: 663 | version "3.0.0" 664 | resolved "https://registry.yarnpkg.com/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz#76e7b7c1f1fb92547374878a562ed06a3e50f6e1" 665 | 666 | lodash._arrayeach@^3.0.0: 667 | version "3.0.0" 668 | resolved "https://registry.yarnpkg.com/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz#bab156b2a90d3f1bbd5c653403349e5e5933ef9e" 669 | 670 | lodash._arraymap@^3.0.0: 671 | version "3.0.0" 672 | resolved "https://registry.yarnpkg.com/lodash._arraymap/-/lodash._arraymap-3.0.0.tgz#1a8fd0f4c0df4b61dea076d717cdc97f0a3c3e66" 673 | 674 | lodash._baseassign@^3.0.0: 675 | version "3.2.0" 676 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" 677 | dependencies: 678 | lodash._basecopy "^3.0.0" 679 | lodash.keys "^3.0.0" 680 | 681 | lodash._baseclone@^3.0.0: 682 | version "3.3.0" 683 | resolved "https://registry.yarnpkg.com/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz#303519bf6393fe7e42f34d8b630ef7794e3542b7" 684 | dependencies: 685 | lodash._arraycopy "^3.0.0" 686 | lodash._arrayeach "^3.0.0" 687 | lodash._baseassign "^3.0.0" 688 | lodash._basefor "^3.0.0" 689 | lodash.isarray "^3.0.0" 690 | lodash.keys "^3.0.0" 691 | 692 | lodash._basecopy@^3.0.0: 693 | version "3.0.1" 694 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" 695 | 696 | lodash._basedifference@^3.0.0: 697 | version "3.0.3" 698 | resolved "https://registry.yarnpkg.com/lodash._basedifference/-/lodash._basedifference-3.0.3.tgz#f2c204296c2a78e02b389081b6edcac933cf629c" 699 | dependencies: 700 | lodash._baseindexof "^3.0.0" 701 | lodash._cacheindexof "^3.0.0" 702 | lodash._createcache "^3.0.0" 703 | 704 | lodash._baseflatten@^3.0.0: 705 | version "3.1.4" 706 | resolved "https://registry.yarnpkg.com/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz#0770ff80131af6e34f3b511796a7ba5214e65ff7" 707 | dependencies: 708 | lodash.isarguments "^3.0.0" 709 | lodash.isarray "^3.0.0" 710 | 711 | lodash._basefor@^3.0.0: 712 | version "3.0.3" 713 | resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2" 714 | 715 | lodash._baseindexof@^3.0.0: 716 | version "3.1.0" 717 | resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" 718 | 719 | lodash._bindcallback@^3.0.0: 720 | version "3.0.1" 721 | resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" 722 | 723 | lodash._cacheindexof@^3.0.0: 724 | version "3.0.2" 725 | resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" 726 | 727 | lodash._createassigner@^3.0.0: 728 | version "3.1.1" 729 | resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" 730 | dependencies: 731 | lodash._bindcallback "^3.0.0" 732 | lodash._isiterateecall "^3.0.0" 733 | lodash.restparam "^3.0.0" 734 | 735 | lodash._createcache@^3.0.0: 736 | version "3.1.2" 737 | resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" 738 | dependencies: 739 | lodash._getnative "^3.0.0" 740 | 741 | lodash._getnative@^3.0.0: 742 | version "3.9.1" 743 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 744 | 745 | lodash._isiterateecall@^3.0.0: 746 | version "3.0.9" 747 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" 748 | 749 | lodash._pickbyarray@^3.0.0: 750 | version "3.0.2" 751 | resolved "https://registry.yarnpkg.com/lodash._pickbyarray/-/lodash._pickbyarray-3.0.2.tgz#1f898d9607eb560b0e167384b77c7c6d108aa4c5" 752 | 753 | lodash._pickbycallback@^3.0.0: 754 | version "3.0.0" 755 | resolved "https://registry.yarnpkg.com/lodash._pickbycallback/-/lodash._pickbycallback-3.0.0.tgz#ff61b9a017a7b3af7d30e6c53de28afa19b8750a" 756 | dependencies: 757 | lodash._basefor "^3.0.0" 758 | lodash.keysin "^3.0.0" 759 | 760 | lodash.assign@^3.2.0: 761 | version "3.2.0" 762 | resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" 763 | dependencies: 764 | lodash._baseassign "^3.0.0" 765 | lodash._createassigner "^3.0.0" 766 | lodash.keys "^3.0.0" 767 | 768 | lodash.clonedeep@^3.0.1: 769 | version "3.0.2" 770 | resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz#a0a1e40d82a5ea89ff5b147b8444ed63d92827db" 771 | dependencies: 772 | lodash._baseclone "^3.0.0" 773 | lodash._bindcallback "^3.0.0" 774 | 775 | lodash.isarguments@^3.0.0: 776 | version "3.1.0" 777 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 778 | 779 | lodash.isarray@^3.0.0: 780 | version "3.0.4" 781 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 782 | 783 | lodash.isplainobject@^3.0.0: 784 | version "3.2.0" 785 | resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz#9a8238ae16b200432960cd7346512d0123fbf4c5" 786 | dependencies: 787 | lodash._basefor "^3.0.0" 788 | lodash.isarguments "^3.0.0" 789 | lodash.keysin "^3.0.0" 790 | 791 | lodash.istypedarray@^3.0.0: 792 | version "3.0.6" 793 | resolved "https://registry.yarnpkg.com/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62" 794 | 795 | lodash.keys@^3.0.0: 796 | version "3.1.2" 797 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 798 | dependencies: 799 | lodash._getnative "^3.0.0" 800 | lodash.isarguments "^3.0.0" 801 | lodash.isarray "^3.0.0" 802 | 803 | lodash.keysin@^3.0.0: 804 | version "3.0.8" 805 | resolved "https://registry.yarnpkg.com/lodash.keysin/-/lodash.keysin-3.0.8.tgz#22c4493ebbedb1427962a54b445b2c8a767fb47f" 806 | dependencies: 807 | lodash.isarguments "^3.0.0" 808 | lodash.isarray "^3.0.0" 809 | 810 | lodash.merge@^3.3.2: 811 | version "3.3.2" 812 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-3.3.2.tgz#0d90d93ed637b1878437bb3e21601260d7afe994" 813 | dependencies: 814 | lodash._arraycopy "^3.0.0" 815 | lodash._arrayeach "^3.0.0" 816 | lodash._createassigner "^3.0.0" 817 | lodash._getnative "^3.0.0" 818 | lodash.isarguments "^3.0.0" 819 | lodash.isarray "^3.0.0" 820 | lodash.isplainobject "^3.0.0" 821 | lodash.istypedarray "^3.0.0" 822 | lodash.keys "^3.0.0" 823 | lodash.keysin "^3.0.0" 824 | lodash.toplainobject "^3.0.0" 825 | 826 | lodash.omit@^3.1.0: 827 | version "3.1.0" 828 | resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-3.1.0.tgz#897fe382e6413d9ac97c61f78ed1e057a00af9f3" 829 | dependencies: 830 | lodash._arraymap "^3.0.0" 831 | lodash._basedifference "^3.0.0" 832 | lodash._baseflatten "^3.0.0" 833 | lodash._bindcallback "^3.0.0" 834 | lodash._pickbyarray "^3.0.0" 835 | lodash._pickbycallback "^3.0.0" 836 | lodash.keysin "^3.0.0" 837 | lodash.restparam "^3.0.0" 838 | 839 | lodash.pick@^3.1.0: 840 | version "3.1.0" 841 | resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-3.1.0.tgz#f252a855b2046b61bcd3904b26f76bd2efc65550" 842 | dependencies: 843 | lodash._baseflatten "^3.0.0" 844 | lodash._bindcallback "^3.0.0" 845 | lodash._pickbyarray "^3.0.0" 846 | lodash._pickbycallback "^3.0.0" 847 | lodash.restparam "^3.0.0" 848 | 849 | lodash.restparam@^3.0.0: 850 | version "3.6.1" 851 | resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" 852 | 853 | lodash.toplainobject@^3.0.0: 854 | version "3.0.0" 855 | resolved "https://registry.yarnpkg.com/lodash.toplainobject/-/lodash.toplainobject-3.0.0.tgz#28790ad942d293d78aa663a07ecf7f52ca04198d" 856 | dependencies: 857 | lodash._basecopy "^3.0.0" 858 | lodash.keysin "^3.0.0" 859 | 860 | lodash@^3.3.1: 861 | version "3.10.1" 862 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" 863 | 864 | lodash@^4.2.0: 865 | version "4.17.4" 866 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 867 | 868 | longest@^1.0.1: 869 | version "1.0.1" 870 | resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" 871 | 872 | loose-envify@^1.0.0: 873 | version "1.3.1" 874 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" 875 | dependencies: 876 | js-tokens "^3.0.0" 877 | 878 | "minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2: 879 | version "3.0.3" 880 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" 881 | dependencies: 882 | brace-expansion "^1.0.0" 883 | 884 | minimist@0.0.8, minimist@~0.0.1: 885 | version "0.0.8" 886 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 887 | 888 | mkdirp@^0.5.0, mkdirp@^0.5.1: 889 | version "0.5.1" 890 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 891 | dependencies: 892 | minimist "0.0.8" 893 | 894 | ms@0.7.3: 895 | version "0.7.3" 896 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" 897 | 898 | mute-stream@0.0.5: 899 | version "0.0.5" 900 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" 901 | 902 | node-fetch@^1.0.1: 903 | version "1.6.3" 904 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" 905 | dependencies: 906 | encoding "^0.1.11" 907 | is-stream "^1.0.1" 908 | 909 | number-is-nan@^1.0.0: 910 | version "1.0.1" 911 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 912 | 913 | object-assign@^4.0.1, object-assign@^4.1.0: 914 | version "4.1.1" 915 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 916 | 917 | once@^1.3.0: 918 | version "1.4.0" 919 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 920 | dependencies: 921 | wrappy "1" 922 | 923 | onetime@^1.0.0: 924 | version "1.1.0" 925 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 926 | 927 | optimist@^0.6.1: 928 | version "0.6.1" 929 | resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" 930 | dependencies: 931 | minimist "~0.0.1" 932 | wordwrap "~0.0.2" 933 | 934 | optionator@^0.6.0: 935 | version "0.6.0" 936 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.6.0.tgz#b63ecbbf0e315fad4bc9827b45dc7ba45284fcb6" 937 | dependencies: 938 | deep-is "~0.1.3" 939 | fast-levenshtein "~1.0.6" 940 | levn "~0.2.5" 941 | prelude-ls "~1.1.1" 942 | type-check "~0.3.1" 943 | wordwrap "~0.0.2" 944 | 945 | os-homedir@^1.0.0: 946 | version "1.0.2" 947 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 948 | 949 | path-is-absolute@^1.0.0: 950 | version "1.0.1" 951 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 952 | 953 | path-is-inside@^1.0.1: 954 | version "1.0.2" 955 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 956 | 957 | pify@^2.0.0: 958 | version "2.3.0" 959 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 960 | 961 | pinkie-promise@^2.0.0: 962 | version "2.0.1" 963 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 964 | dependencies: 965 | pinkie "^2.0.0" 966 | 967 | pinkie@^2.0.0: 968 | version "2.0.4" 969 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 970 | 971 | prelude-ls@~1.1.0, prelude-ls@~1.1.1, prelude-ls@~1.1.2: 972 | version "1.1.2" 973 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 974 | 975 | process-nextick-args@~1.0.6: 976 | version "1.0.7" 977 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 978 | 979 | promise@^7.1.1: 980 | version "7.1.1" 981 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" 982 | dependencies: 983 | asap "~2.0.3" 984 | 985 | prop-types@^15.5.8: 986 | version "15.5.8" 987 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394" 988 | dependencies: 989 | fbjs "^0.8.9" 990 | 991 | react-clone-referenced-element@^1.0.1: 992 | version "1.0.1" 993 | resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682" 994 | 995 | react-mixin@^3.0.3: 996 | version "3.0.5" 997 | resolved "https://registry.yarnpkg.com/react-mixin/-/react-mixin-3.0.5.tgz#e0b7b6713fdc9ddc429267df808b6ac5184c6706" 998 | dependencies: 999 | object-assign "^4.0.1" 1000 | smart-mixin "^2.0.0" 1001 | 1002 | react-native-timer-mixin@^0.11.0: 1003 | version "0.11.0" 1004 | resolved "https://registry.yarnpkg.com/react-native-timer-mixin/-/react-native-timer-mixin-0.11.0.tgz#acd7e267ac6666970c2ed2186f6a4484cc7833d8" 1005 | 1006 | readable-stream@^2.2.2: 1007 | version "2.2.9" 1008 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" 1009 | dependencies: 1010 | buffer-shims "~1.0.0" 1011 | core-util-is "~1.0.0" 1012 | inherits "~2.0.1" 1013 | isarray "~1.0.0" 1014 | process-nextick-args "~1.0.6" 1015 | string_decoder "~1.0.0" 1016 | util-deprecate "~1.0.1" 1017 | 1018 | readline2@^1.0.1: 1019 | version "1.0.1" 1020 | resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" 1021 | dependencies: 1022 | code-point-at "^1.0.0" 1023 | is-fullwidth-code-point "^1.0.0" 1024 | mute-stream "0.0.5" 1025 | 1026 | regenerator-runtime@^0.10.0: 1027 | version "0.10.5" 1028 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" 1029 | 1030 | repeat-string@^1.5.2: 1031 | version "1.6.1" 1032 | resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 1033 | 1034 | restore-cursor@^1.0.1: 1035 | version "1.0.1" 1036 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 1037 | dependencies: 1038 | exit-hook "^1.0.0" 1039 | onetime "^1.0.0" 1040 | 1041 | right-align@^0.1.1: 1042 | version "0.1.3" 1043 | resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" 1044 | dependencies: 1045 | align-text "^0.1.1" 1046 | 1047 | rimraf@^2.2.8: 1048 | version "2.6.1" 1049 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" 1050 | dependencies: 1051 | glob "^7.0.5" 1052 | 1053 | run-async@^0.1.0: 1054 | version "0.1.0" 1055 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" 1056 | dependencies: 1057 | once "^1.3.0" 1058 | 1059 | rx-lite@^3.1.2: 1060 | version "3.1.2" 1061 | resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" 1062 | 1063 | setimmediate@^1.0.5: 1064 | version "1.0.5" 1065 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 1066 | 1067 | shelljs@^0.5.3: 1068 | version "0.5.3" 1069 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.5.3.tgz#c54982b996c76ef0c1e6b59fbdc5825f5b713113" 1070 | 1071 | smart-mixin@^2.0.0: 1072 | version "2.0.0" 1073 | resolved "https://registry.yarnpkg.com/smart-mixin/-/smart-mixin-2.0.0.tgz#a34a1055e32a75b30d2b4e3ca323dc99cb53f437" 1074 | 1075 | source-map@^0.4.4: 1076 | version "0.4.4" 1077 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" 1078 | dependencies: 1079 | amdefine ">=0.0.4" 1080 | 1081 | source-map@~0.5.1: 1082 | version "0.5.6" 1083 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" 1084 | 1085 | sprintf-js@~1.0.2: 1086 | version "1.0.3" 1087 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1088 | 1089 | string-width@^1.0.1: 1090 | version "1.0.2" 1091 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1092 | dependencies: 1093 | code-point-at "^1.0.0" 1094 | is-fullwidth-code-point "^1.0.0" 1095 | strip-ansi "^3.0.0" 1096 | 1097 | string_decoder@~1.0.0: 1098 | version "1.0.0" 1099 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" 1100 | dependencies: 1101 | buffer-shims "~1.0.0" 1102 | 1103 | strip-ansi@^3.0.0: 1104 | version "3.0.1" 1105 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1106 | dependencies: 1107 | ansi-regex "^2.0.0" 1108 | 1109 | strip-json-comments@~1.0.1: 1110 | version "1.0.4" 1111 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" 1112 | 1113 | supports-color@^2.0.0: 1114 | version "2.0.0" 1115 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1116 | 1117 | text-table@~0.2.0: 1118 | version "0.2.0" 1119 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1120 | 1121 | through@^2.3.6: 1122 | version "2.3.8" 1123 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1124 | 1125 | to-fast-properties@^1.0.1: 1126 | version "1.0.3" 1127 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" 1128 | 1129 | tryit@^1.0.1: 1130 | version "1.0.3" 1131 | resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" 1132 | 1133 | type-check@~0.3.1: 1134 | version "0.3.2" 1135 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 1136 | dependencies: 1137 | prelude-ls "~1.1.2" 1138 | 1139 | typedarray@^0.0.6: 1140 | version "0.0.6" 1141 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1142 | 1143 | ua-parser-js@^0.7.9: 1144 | version "0.7.12" 1145 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" 1146 | 1147 | uglify-js@^2.6: 1148 | version "2.8.22" 1149 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0" 1150 | dependencies: 1151 | source-map "~0.5.1" 1152 | yargs "~3.10.0" 1153 | optionalDependencies: 1154 | uglify-to-browserify "~1.0.0" 1155 | 1156 | uglify-to-browserify@~1.0.0: 1157 | version "1.0.2" 1158 | resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" 1159 | 1160 | user-home@^2.0.0: 1161 | version "2.0.0" 1162 | resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" 1163 | dependencies: 1164 | os-homedir "^1.0.0" 1165 | 1166 | util-deprecate@~1.0.1: 1167 | version "1.0.2" 1168 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1169 | 1170 | whatwg-fetch@>=0.10.0: 1171 | version "2.0.3" 1172 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" 1173 | 1174 | window-size@0.1.0: 1175 | version "0.1.0" 1176 | resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" 1177 | 1178 | wordwrap@0.0.2: 1179 | version "0.0.2" 1180 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" 1181 | 1182 | wordwrap@~0.0.2: 1183 | version "0.0.3" 1184 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" 1185 | 1186 | wrappy@1: 1187 | version "1.0.2" 1188 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1189 | 1190 | write@^0.2.1: 1191 | version "0.2.1" 1192 | resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" 1193 | dependencies: 1194 | mkdirp "^0.5.1" 1195 | 1196 | xml-escape@~1.0.0: 1197 | version "1.0.0" 1198 | resolved "https://registry.yarnpkg.com/xml-escape/-/xml-escape-1.0.0.tgz#00963d697b2adf0c185c4e04e73174ba9b288eb2" 1199 | 1200 | xtend@^4.0.0: 1201 | version "4.0.1" 1202 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 1203 | 1204 | yargs@~3.10.0: 1205 | version "3.10.0" 1206 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" 1207 | dependencies: 1208 | camelcase "^1.0.2" 1209 | cliui "^2.1.0" 1210 | decamelize "^1.0.0" 1211 | window-size "0.1.0" 1212 | --------------------------------------------------------------------------------