├── .DS_Store
├── CHANGELOG.md
├── README.md
├── example
├── .babelrc
├── .buckconfig
├── .flowconfig
├── .gitattributes
├── .gitignore
├── .watchmanconfig
├── __tests__
│ ├── index.android.js
│ └── index.ios.js
├── android
│ ├── app
│ │ ├── BUCK
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── MainApplication.java
│ │ │ └── res
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── keystores
│ │ ├── BUCK
│ │ └── debug.keystore.properties
│ └── settings.gradle
├── app.json
├── index.android.js
├── index.ios.js
├── ios
│ ├── example-tvOS
│ │ └── Info.plist
│ ├── example-tvOSTests
│ │ └── Info.plist
│ ├── example.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── example-tvOS.xcscheme
│ │ │ └── example.xcscheme
│ ├── example
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.xib
│ │ ├── Images.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ └── main.m
│ └── exampleTests
│ │ ├── Info.plist
│ │ └── exampleTests.m
├── package-lock.json
├── package.json
├── src
│ ├── components
│ │ └── SliderEntry.js
│ ├── index.js
│ ├── static
│ │ └── entries.js
│ └── styles
│ │ ├── SliderEntry.style.js
│ │ └── index.style.js
└── yarn.lock
├── package-lock.json
├── package.json
├── src
├── carousel
│ └── Carousel.js
├── index.js
├── pagination
│ ├── Pagination.js
│ ├── Pagination.style.js
│ ├── PaginationDot.js
│ └── README.md
└── parallaximage
│ ├── ParallaxImage.js
│ ├── ParallaxImage.style.js
│ └── README.md
└── yarn.lock
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/react-native-snap-carousel/8f65a9af47c7943d5319966f37458fef8f4e244e/.DS_Store
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## v3.0.0
2 | ### Breaking changes
3 | * Plugin is now built on top of `FlatList`, which allows for huge performance optimizations. From now on, items must be rendered using props `data` and `renderItem`.
4 | ### General
5 | * Add `ParallaxImage` component (see the specific documentation [here](https://github.com/archriss/react-native-snap-carousel/blob/master/src/parallaximage/README.md))
6 | * Add prop `activeSlideAlignment`
7 | * Fix issue with autoplay when setting `scrollEnabled` to `false`
8 | * Prevent going back to the first item when overscrolling the last one
9 | * Prevent callback from being called at the wrong time in some specific scenarios
10 |
11 | ## v2.4.0
12 | * Add `Pagination` component (see the specific documentation [here](https://github.com/archriss/react-native-snap-carousel/blob/master/src/pagination/README.md))
13 | * Allow `firstItem` to be changed dynamically
14 | * Allow `0` value for `carouselHorizontalPadding` and `carouselVerticalPadding` (thanks [@bonbonez](https://github.com/bonbonez))
15 | * Keep the easing of slide's opacity animation linear
16 | * Use native driver for slide's animation (can be overridden via `animationOptions`)
17 |
18 | ## v2.3.1
19 | * Fix issue when snap is disabled
20 |
21 | ## v2.3.0
22 | * Refactor callback handling to provide a more reliable solution when momentum is disabled
23 | * Fix issue with parallel animations (thanks [@jnbt](https://github.com/jnbt))
24 | * Prevent calls to `undefined` interpolators when working with dynamic slides (thanks [@cskaynar](https://github.com/cskaynar))
25 | * Improve vertical mode
26 | * Add prop `scrollEndDragDebounceValue`
27 | * Expose current scroll position with `this.currentScrollPosition`
28 | * Remove props `scrollEndDragThrottleValue` and `snapCallbackDebounceValue` (use `scrollEndDragDebounceValue` instead)
29 |
30 | ## v2.2.2
31 | * Fix issue that prevented inactive styles of first and last items to be applied when using `snapToPrev` and `snapToNext` methods
32 |
33 | ## v2.2.1
34 | * Do not mark `sliderWidth` and `sliderHeight` as required
35 | * Add warnings when properties specific to carousel's orientation haven't been set
36 |
37 | ## v2.2.0
38 | * Implement vertical mode (prop `vertical`)
39 | * Make sure that current active item is properly updated when snapping
40 | * Prevent issues when 'sliderWidth' is smaller than viewport's width
41 | * Recalculate card positions on layout to handle rotation (thanks [@andrewpope](https://github.com/andrewpope)); make sure to read [this note](https://github.com/archriss/react-native-snap-carousel#handling-device-rotation)
42 | * Refresh card positions if slider and/or item's dimensions are updated (thanks [@hoangnm](https://github.com/hoangnm))
43 | * Add props `scrollEndDragThrottleValue` and `snapCallbackDebounceValue`
44 | * Expose `View`'s `onLayout` prop
45 | * Deprecate prop `onScrollViewScroll`
46 |
47 | ## v2.1.4
48 | * Add prop `onScrollViewScroll`
49 |
50 | ## v2.1.3
51 | * Default value for `showsHorizontalScrollIndicator` is now `false`
52 | * Expose `ScrollView`'s `onSscroll` prop (thanks [@radko93](https://github.com/radko93))
53 |
54 | ## v2.1.2
55 | * Do not trigger `onSnapToItem` when snapping back to the same slide (thanks [@rgabs](https://github.com/rgabs))
56 | * Add prop `carouselHorizontalPadding` to override container's inner padding (thanks [@skeie](https://github.com/skeie))
57 |
58 | ## v2.1.1
59 | * Ensure compatibility with RN 0.43 (previous version of plugin's dependency `react-addons-shallow-compare` was breaking with React 16)
60 | * Fix issue with padding on iOS that could cause the carousel to snap back when its last item was clicked
61 |
62 | ## v2.1.0
63 | * Add RTL support
64 | * Keep current active item when adding slides dynamically
65 | * Prevent invalid `firstItem` number
66 | * Add prop `activeSlideOffset`
67 |
68 | ## v2.0.3
69 |
70 | * Prevent error when carousel has only one child (thanks [@kevinvandijk](https://github.com/kevinvandijk))
71 | * Fix issue when appending dynamic slides (the first one was ignored)
72 | * Fix edge case that prevented the first slide from being focused when swiping back with momentum enabled
73 | * Bump example's RN version to 0.42.3
74 |
75 | ## v2.0.2
76 |
77 | * Make sure that scroll indicator is hidden by default
78 |
79 | ## v2.0.1
80 |
81 | * Fix un-handled exception with interpolators (thanks [@chitezh](https://github.com/chitezh))
82 |
83 | ## v2.0.0
84 |
85 | * Items are now direct children of the `` component, which makes it easier to use (thanks [@Jonarod](https://github.com/Jonarod))
86 | * Props `items` and `renderItem` have been removed
87 |
88 | ## v1.6.1
89 |
90 | * Due to some touch events being buggy, rework methods so the children will receive touch events on Android
91 |
92 | ## v1.6.0
93 |
94 | * Add prop `enableMomentum`
95 | * Fix an infinite-loop on iOS with momentum enabled
96 | * Fix the snapping effect when releasing touch without interia on iOS with momentum enabled
97 | * Fix autoplay on Android, it should start and stop properly and stop being triggered while swiping
98 | * Use `View.propTypes.style` instead of `PropTypes.number` in styles validation (thanks [@pesakitan22](https://github.com/pesakitan22))
99 |
100 | ## v1.5.0
101 |
102 | * Items length can now be changed on-the-fly (thanks [@superical](https://github.com/superical))
103 | * Now handling momentum (thanks [@FakeYou](https://github.com/FakeYou))
104 |
105 | ## v1.4.0
106 |
107 | * Better update strategy with shallowCompare
108 | * Add `snapToNext()`, `snapToPrev()`, `currentIndex` methods and properties
109 |
110 | ## v1.3.1
111 |
112 | * Properly center on first item when mounting component on Android (potentially iOS too)
113 |
114 | ## v1.3.0
115 |
116 | * Pass the item data as the 2nd param of `onSnapToItem` callback
117 |
118 | ## v1.2.1
119 |
120 | * Fix reference call when the component has been unmounted
121 |
122 | ## v1.2.0
123 |
124 | * Add prop `onSnapToItem`
125 |
126 | ## v1.1.0
127 |
128 | * Center slides properly
129 | * Handle one slide only
130 | * Add props `inactiveSlideScale`, `inactiveSlideOpacity`, `containerCustomStyle` and `contentContainerCustomStyle`
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-snap-carousel
2 | Swiper component for React Native featuring **previews**, **snapping effect**, **parallax images**, **performant handling of huge numbers of items**, and **RTL support**. Compatible with Android & iOS.
3 |
4 | 
5 | [](https://www.npmjs.com/package/react-native-snap-carousel)
6 | [](https://github.com/archriss/react-native-snap-carousel/releases)
7 | [](https://github.com/archriss/react-native-snap-carousel/issues)
8 | [](https://github.com/archriss/react-native-snap-carousel/issues?q=is%3Aissue+is%3Aclosed)
9 |
10 | ## Table of contents
11 |
12 | 1. [Showcase](#showcase)
13 | 1. [Usage](#usage)
14 | 1. [Migration from version 2.x](#migration-from-version-2x)
15 | 1. [Props](#props)
16 | 1. [Methods](#methods)
17 | 1. [Getters](#getters)
18 | 1. [Example](#example)
19 | 1. [`ParallaxImage` component](#parallaximage-component)
20 | 1. [`Pagination` component](#pagination-component)
21 | 1. [Tips and tricks](#tips-and-tricks)
22 | 1. [Known issues](#known-issues)
23 | 1. [TODO](#todo)
24 | 1. [Credits](#credits)
25 |
26 | ## Showcase
27 |
28 | ### Archriss' "Ville d'Aix-en-Provence" app
29 |
30 | **The React Native version of this app (6.0.0) is going to be available on [Android](https://play.google.com/store/apps/details?id=fr.archriss.aixmobile.app) and [iOS](https://itunes.apple.com/fr/app/ville-daix-en-provence/id494548366?mt=8) by mid-september** (the current one is Cordova-powered). It uses **version 3.0.0** of the plugin, with `FlatList`'s implementation and [parallax images](#parallaximage-component).
31 |
32 | 
33 | 
34 |
35 | ### Archriss' showcase app
36 |
37 | **You can try the app live on [Android](https://play.google.com/store/apps/details?id=fr.archriss.demo.app) and [iOS](https://itunes.apple.com/lu/app/archriss-presentation-mobile/id1180954376?mt=8).** It currently uses **version 1.4.0** of the plugin. Be aware that sliders' layouts will break on RTL devices since support was added in version 2.1.0 (see [#38](https://github.com/archriss/react-native-snap-carousel/issues/38)).
38 |
39 | 
40 | 
41 | 
42 |
43 | > Please note that **we do not plan on Open-Sourcing the code of our showcase app**. Still, we've put together [an example](#example) for you to play with, and you can find some insight about our map implementation [in this comment](https://github.com/archriss/react-native-snap-carousel/issues/11#issuecomment-265147385).
44 | > The folks at [codedaily.io](https://codedaily.io) have put together a great tutorial about implementing a similar feature. [Go check it out!](https://codedaily.io/tutorials/9/Build-a-Map-with-Custom-Animated-Markers-and-Region-Focus-when-Content-is-Scrolled-in-React-Native)
45 |
46 | ## Usage
47 |
48 | ```
49 | $ npm install --save react-native-snap-carousel
50 | ```
51 |
52 | ```javascript
53 | import Carousel from 'react-native-snap-carousel';
54 |
55 | export class MyCarousel extends Component {
56 |
57 | _renderItem ({item, index}) {
58 | return (
59 |
60 | { item.title }
61 |
62 | );
63 | }
64 |
65 | render () {
66 | return (
67 | { this._carousel = c; }}
69 | data={this.state.entries}
70 | renderItem={this._renderItem}
71 | sliderWidth={sliderWidth}
72 | itemWidth={itemWidth}
73 | />
74 | );
75 | }
76 | }
77 | ```
78 |
79 | ## Migration from version 2.x
80 |
81 | Slides are no longer appended as direct children of the component. There are two new props that takes care of their rendering: `data` and `renderItem` (both are inherited from `FlatList`).
82 |
83 | If you were already looping throught an array of data to populate the carousel, the migration is pretty straightforward. Just pass your slides' data to the `data` prop, convert your slides' getter to a function and pass it to the `renderItem` prop: you're good to go!
84 |
85 | **From**
86 | ```javascript
87 | get slides () {
88 | return this.state.entries.map((entry, index) => {
89 | return (
90 |
91 | { entry.title }
92 |
93 | );
94 | });
95 | }
96 |
97 | render () {
98 | return (
99 |
103 | { this.slides }
104 |
105 | );
106 | }
107 | ```
108 |
109 | **To**
110 | ```javascript
111 | _renderItem ({item, index}) {
112 | return (
113 |
114 | { item.title }
115 |
116 | );
117 | }
118 |
119 | render () {
120 | return (
121 |
127 | );
128 | }
129 | ```
130 |
131 | > Note that the `key` prop is no longer needed for carousel's items. If you want to provide a custom key, you should pass your own [`keyExtractor`](https://facebook.github.io/react-native/docs/flatlist.html#keyextractor) to the ``.
132 |
133 | If you were previously appending random types of children, you will need to rely on a specific bit of data to return the proper element from your `renderItem` function.
134 |
135 | **Example**
136 | ```javascript
137 | _renderItem ({item, index}) {
138 | if (item.type === 'text') {
139 | return ;
140 | } else if (item.type === 'image') {
141 | return ;
142 | } else {
143 | return ;
144 | }
145 | }
146 | ```
147 |
148 | ## Props
149 |
150 | ### Required
151 |
152 | Prop | Description | Type | Default
153 | ------ | ------ | ------ | ------
154 | **data** | Array of items to loop on | Array | **Required**
155 | **renderItem** | Takes an item from data and renders it into the list. The function receives one argument `{item, index}` (see [Usage](#usage)) and must return a React element. | Function | **Required**
156 | **itemWidth** | Width in pixels of carousel's items, **must be the same for all of them** | Number | **Required for __horizontal__ carousel**
157 | **sliderWidth** | Width in pixels of the carousel itself | Number | **Required for __horizontal__ carousel**
158 | **itemHeight** | Height in pixels of carousel's items, **must be the same for all of them** | Number | **Required for __vertical__ carousel**
159 | **sliderHeight** | Height in pixels of the carousel itself | Number | **Required for __vertical__ carousel**
160 |
161 | ### Behavior
162 |
163 | Prop | Description | Type | Default
164 | ------ | ------ | ------ | ------
165 | activeSlideOffset | From slider's center, minimum slide distance to be scrolled before being set to active | Number | `25`
166 | apparitionDelay | `FlatList`'s init is a real mess, with lots of unneeded flickers and slides movement. This prop controls the delay during which the carousel will be hidden when mounted. | Number | `250`
167 | enableMomentum | See [momentum](#momentum) | Boolean | `false`
168 | enableSnap | If enabled, releasing the touch will scroll to the center of the nearest/active item | Boolean | `true`
169 | firstItem | Index of the first item to display | Number | `0`
170 | hasParallaxImages | Whether the carousel contains `` components or not. Required for specific data to be passed to children. | Boolean | `false`
171 | scrollEndDragDebounceValue | **When momentum is disabled**, this prop defines the timeframe during which multiple callback calls should be "grouped" into a single one. This debounce also helps smoothing the snap effect by providing a bit of inertia when touch is released. **Note that this will delay callback's execution.** | Number | `50` for iOS, `150` for Android
172 | shouldOptimizeUpdates | Whether to implement a `shouldComponentUpdate` strategy to minimize updates | Boolean | `true`
173 | snapOnAndroid | Snapping on android is sometimes choppy, especially when swiping quickly, so you can disable it | Boolean | `true`
174 | swipeEnabled | When disabled, the view cannot be scrolled via touch interaction. It takes advantage of `ScrollView`'s prop `scrollEnabled`, with just a tiny tweak regarding autoplay. | Boolean | `true`
175 | swipeThreshold | Delta x when swiping to trigger the snap | Number | `20`
176 | useNativeOnScroll | Move `onScroll` events to the native thread in order to prevent the tiny lag associated with RN's JS bridge. **Activate this if you have a `transform` and/or `opacity` animation that needs to follow carousel's scroll position closely**. More info in [this post](https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html). Note that it will be activated if `hasParallaxImages` is set to `true` and/or if `scrollEventThrottle` is set to less than `16`. | Boolean | `false`
177 | vertical | Layout slides vertically instead of horizontally | Boolean | `false`
178 |
179 | ### Autoplay
180 |
181 | Prop | Description | Type | Default
182 | ------ | ------ | ------ | ------
183 | autoplay | Trigger autoplay on mount. **Warning: this prop cannot be changed dynamically.** | Boolean | `false`
184 | autoplayDelay | Delay before enabling autoplay on startup & after releasing the touch | Number | `5000`
185 | autoplayInterval | Delay in ms until navigating to the next item | Number | `3000`
186 |
187 | ### Style and animation
188 |
189 | Prop | Description | Type | Default
190 | ------ | ------ | ------ | ------
191 | activeSlideAlignment | Determine active slide's alignment relative to the carousel. Possible values are: `'start'`, `'center'` and `'end'`. | String | `'center'`
192 | animationFunc | Animated animation to use; you must provide the name of the method. Note that it will only be applied to the scale animation since opacity's animation type will always be set to `timing` (no one wants the opacity to 'bounce' around) | String | `timing`
193 | animationOptions | Animation options to be merged with the default ones. Can be used without `animationFunc`. Note that opacity's easing will be kept linear. | Object | `{ duration: 600, easing: Easing.elastic(1) }`
194 | containerCustomStyle | Optional styles for Scrollview's global wrapper | View Style Object | `{}`
195 | contentContainerCustomStyle | Optional styles for Scrollview's items container | View Style Object | `{}`
196 | inactiveSlideOpacity | Value of the opacity effect applied to inactive slides | Number | `1`
197 | inactiveSlideScale | Value of the 'scale' transform applied to inactive slides | Number | `0.9`
198 | slideStyle | Optional style for each item's container (the one whose scale and opacity are animated) | Animated View Style Object | {}
199 |
200 | ### Callbacks
201 |
202 | Prop | Description | Type | Default
203 | ------ | ------ | ------ | ------
204 | onLayout(event) | Exposed `View` callback; invoked on mount and layout changes | Function | `undefined`
205 | onScroll(event) | Exposed `ScrollView` callback; fired while scrolling | Function | `undefined`
206 | onSnapToItem(slideIndex) | Callback fired when navigating to an item | Function | `undefined`
207 |
208 | ### Inherited props
209 |
210 | The component is built on top of the `FlatList` component, meaning it inherits from [`FlatList`](https://facebook.github.io/react-native/docs/flatlist.html), [`VirtualizedList`](https://facebook.github.io/react-native/docs/virtualizedlist.html), and [`ScrollView`](https://facebook.github.io/react-native/docs/scrollview.html).
211 |
212 | You can use almost all props from this three components, but some of them can't be overriden because it would mess with our implementation's logic.
213 |
214 | Here are a few useful props regarding carousel's **style and "feeling"**: `showsHorizontalScrollIndicator`, `scrollEnabled` (if you want to scroll only programmatically), `overScrollMode` (android), `bounces` (ios), `decelerationRate` (ios), `scrollEventThrottle` (ios).
215 |
216 | And here are some useful ones for **performance optimizations and rendering**: `initialNumToRender`, `maxToRenderPerBatch`, `windowSize`, `updateCellsBatchingPeriod`, `extraData`, `removeClippedSubviews` (the latter may have bugs, as stated in [RN's doc](https://facebook.github.io/react-native/docs/flatlist.html#removeclippedsubviews)). The first three are already implemented with default parameters, but you can override them if they don't suit your needs.
217 |
218 | ## Methods
219 |
220 | ### Reference to the component
221 |
222 | In order to use the following methods, you need to create a reference to the carousel's instance. There are two ways of doing it.
223 |
224 | #### ref as a callback attribute (**recommended**)
225 | ```javascript
226 | { this._carousel = c; }}
229 | />
230 |
231 | // methods can then be called this way
232 | onPress={() => { this._carousel.snapToNext(); }}
233 | ```
234 |
235 | #### ref as a string attribute ([legacy](http://stackoverflow.com/questions/37468913/why-ref-string-is-legacy))
236 | ```javascript
237 |
241 |
242 | // methods can then be called this way
243 | onPress={() => { this.refs.carousel.snapToNext(); }}
244 | ```
245 |
246 | ### Available methods
247 |
248 | Method | Description
249 | ------ | ------
250 | `startAutoplay (instantly = false)` | Start the autoplay manually
251 | `stopAutoplay ()` | Stop the autoplay manually
252 | `snapToItem (index, animated = true)` | Snap to an item manually
253 | `snapToNext (animated = true)` | Snap to next item manually
254 | `snapToPrev (animated = true)` | Snap to previous item manually
255 |
256 | ## Getters
257 |
258 | > You need a reference to the carousel's instance (see [above](#reference-to-the-component) if needed).
259 |
260 | Property | Description
261 | ------ | ------
262 | `currentIndex` | Current active item (`int`, starts at 0)
263 | `currentScrollPosition` | Underlying `ScrollView`'s current content offset (`int`, starts at `0` if `activeSlideAlignment` is set to `start`, negative value otherwise)
264 |
265 | ## Example
266 | You can find the following example in the [/example](https://github.com/archriss/react-native-snap-carousel/tree/master/example) folder.
267 |
268 | 
269 |
270 | ## `ParallaxImage` component
271 |
272 | Version `3.0.0` introduced a `` component, an image component aware of carousel's current scroll position and therefore able to display a nice parallax effect.
273 |
274 | 
275 |
276 | You can find the documentation for this component [here](https://github.com/archriss/react-native-snap-carousel/blob/flatlist/src/parallaximage/README.md).
277 |
278 | ## `Pagination` component
279 |
280 | Starting with version `2.4.0`, a customizable `` component has been added. This is how it looks like with its default configuration:
281 |
282 | 
283 |
284 | You can find the documentation for this component [here](https://github.com/archriss/react-native-snap-carousel/blob/master/src/pagination/README.md).
285 |
286 | ## Tips and tricks
287 |
288 | ### Momentum
289 |
290 | Since version `1.5.0`, the snapping effect can be based on momentum (by setting `enableMomentum` to `true`) instead of when you're releasing your finger. It means that the component will wait until the `ScrollView` isn't moving anymore to snap.
291 |
292 | By default, the inertia isn't too high on Android. However, we had to tweak the default iOS value a bit to make sure the snapping isn't delayed for too long. You can adjust this value to your needs thanks to [this prop](https://facebook.github.io/react-native/docs/scrollview.html#decelerationrate).
293 |
294 | If momentum is disabled (default behavior), make sure to play with prop `scrollEndDragDebounceValue` since it can help achieving a better snap feeling.
295 |
296 | > **We recommend setting `enableMomentum` to `false` (default) and `decelerationRate` to `'fast'` when you are displaying only one main slide** (as in the showcase above), and to use `true` and `0.9` otherwise.
297 |
298 | ### Margin between slides
299 | If you need some **extra horizontal margin** between slides (besides the one resulting from the scale effect), you should add it as `paddingHorizontal` on slide's container. Make sure to take this into account when calculating item's width.
300 |
301 | ```javascript
302 | const horizontalMargin = 20;
303 | const slideWidth = 280;
304 |
305 | const sliderWidth = Dimensions.get('window').width;
306 | const itemWidth = slideWidth + horizontalMargin * 2;
307 | const itemHeight = 200;
308 |
309 | const styles = Stylesheet.create({
310 | slide: {
311 | width: itemWidth,
312 | height: itemHeight
313 | // other styles for your item's container
314 | }
315 | };
316 | ```
317 |
318 | ### Handling device rotation
319 |
320 | Since version 2.2.0, slides will re-center properly if you update slider and/or items' dimensions when `onLayout` is fired.
321 |
322 | Here is an example of a working implementation (thanks [@andrewpope](https://github.com/archriss/react-native-snap-carousel/pull/76#issuecomment-306187425)):
323 |
324 | ```
325 | constructor(props) {
326 | super(props);
327 | this.state = {
328 | viewport: {
329 | width: Dimensions.get('window').width,
330 | height: Dimensions.get('window').height
331 | }
332 | };
333 | }
334 |
335 | render() {
336 | return (
337 | {
339 | this.setState({
340 | viewport: {
341 | width: Dimensions.get('window').width,
342 | height: Dimensions.get('window').height
343 | }
344 | });
345 | }}
346 | >
347 | { this.carousel = c; } }
349 | sliderWidth={this.state.viewport.width}
350 | itemWidth={this.state.viewport.width}
351 | ...
352 | />
353 |
354 | );
355 | }
356 | ```
357 |
358 | ### Fullscreen slides
359 |
360 | While the plugin hasn't been designed with this use case in mind, you can easily implement fullscreen slides. The following code should serve as a good starting point.
361 |
362 | ```javascript
363 | const { width: viewportWidth, height: viewportHeight } = Dimensions.get('window');
364 |
365 | export class MyCarousel extends Component {
366 |
367 | _renderItem ({item, index}) {
368 | return (
369 | // or { flex: 1 } for responsive height
370 | );
371 | }
372 |
373 | render () {
374 | return (
375 |
384 | );
385 | }
386 | }
387 | ```
388 |
389 | [This plugin](https://github.com/shichongrui/react-native-on-layout) can also prove useful.
390 |
391 | ### Android performances
392 |
393 | Make sure to test carousel's performances **without JS Dev Mode enabled**.
394 |
395 | It can take user experience from "crappy and sluggish" to "pretty good" - it's Android though, so nothing like "perfect" or "incredibly smooth"...
396 |
397 |
398 | ### Understanding styles
399 |
400 | Here is a screenshot that should help you understand how each of the above variables is used.
401 |
402 | 
403 |
404 | ## Known issues
405 |
406 | ### FlatList and ScrollView's limitations
407 |
408 | Note that this plugin is built on top of React Native's `FlatList` which, in turn, is based on `ScrollView`. Unfortunately, its implementation shows flaws that affect the plugin, the main ones being the following:
409 | - there is no `scrollEnd` event
410 | - `scrollTo` method doesn't accept any callback
411 | - Android's `scrollTo` animation is quite brutal.
412 |
413 | On top of that, `FlatList` has its own set of bugs and buggy behaviors.
414 |
415 | We're trying to work around these issues, but the result is not always as smooth as we'd want it to be. Keep that in mind and go spam [React Native's Feature Request](https://react-native.canny.io/feature-requests) ;-)
416 |
417 | ### Unreliable callbacks
418 |
419 | When `enableMomentum` is disabled, providing a reliable callback is really tricky since no `scrollEnd` event has been exposed yet for the `ScrollView` component. We can only rely on the `scrollDragEnd` event, which comes with a huge bunch of issues. See [#34](https://github.com/archriss/react-native-snap-carousel/issues/34) for more information.
420 |
421 | Version 2.3.0 tackled these issues with a bunch of flags and hacks. But you could still be facing the following one: **when you build a debug version of your app without enabling JS remote debugging**, timers will desynchronize and callbacks will be a complete mess. Try to either enable remote debugging or build a production version of your app, and everything should get back to normal.
422 |
423 | ### Error with Jest
424 |
425 | You might encounter the following error when using the plugin in conjonction with Jest: `TypeError: Cannot read property 'style' of undefined at Object.`.
426 |
427 | As you can see [here](https://github.com/facebook/react-native/blob/master/jest/setup.js), this is because React Native mocks `ScrollView` for you when you write unit tests with Jest.
428 |
429 | The easiest workaround is to add `jest.unmock('ScrollView')` before importing the component in your test file (thanks [@hoangnm](https://github.com/hoangnm) for the tip!).
430 |
431 | ### React Native version
432 |
433 | **RN 0.44.x is the minimum version required to use the plugin.**
434 |
435 | Bear in mind that we follow RN evolutions closely, which means newer versions of the plugin might break when used in conjunction with a version of RN that is not the latest stable one.
436 |
437 | ### RTL support (experimental)
438 |
439 | Since version 2.1.0, the plugin is compatible with RTL layouts. Our implementation relies on miscellaneous hacks that work around a [React Native bug](https://github.com/facebook/react-native/issues/11960) with horizontal `ScrollView`.
440 |
441 | As such, this feature should be considered experimental since it might break with newer versions of React Native.
442 |
443 | ## TODO
444 |
445 | - [ ] Implement 'loop' mode
446 | - [ ] Handle changing major props on-the-fly
447 | - [ ] Handle autoplay properly when updating children's length
448 | - [x] Add parallax image component
449 | - [x] Base the plugin on `FlatList` instead of `ScrollView`
450 | - [x] Add alignment option
451 | - [x] Add pagination component
452 | - [x] Add vertical implementation
453 | - [x] Handle device orientation event (see [this note] (https://github.com/archriss/react-native-snap-carousel#handling-device-rotation))
454 | - [x] Add RTL support
455 | - [x] Improve momemtum handling
456 | - [x] Improve snap on Android
457 | - [x] Handle passing 1 item only
458 | - [x] Fix centering
459 |
460 | ## Credits
461 |
462 | Written by [Maxime Bertonnier](https://fr.linkedin.com/in/maxime-bertonnier-744351aa) ([Exilz](https://github.com/Exilz)) and [Benoît Delmaire](https://fr.linkedin.com/in/benoitdelmaire) ([bd-arc](https://github.com/bd-arc)) at
463 | [Archriss](http://www.archriss.com/).
464 |
--------------------------------------------------------------------------------
/example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react-native"]
3 | }
--------------------------------------------------------------------------------
/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/.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
--------------------------------------------------------------------------------
/example/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 |
33 | # node.js
34 | #
35 | node_modules/
36 | npm-debug.log
37 | yarn-error.log
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
50 |
51 | fastlane/report.xml
52 | fastlane/Preview.html
53 | fastlane/screenshots
54 |
--------------------------------------------------------------------------------
/example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/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/__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/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.rndiffapp",
49 | )
50 |
51 | android_resource(
52 | name = "res",
53 | package = "com.rndiffapp",
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 | )
--------------------------------------------------------------------------------
/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.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-linear-gradient')
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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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.BV.LinearGradient.LinearGradientPackage;
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 LinearGradientPackage()
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 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/react-native-snap-carousel/8f65a9af47c7943d5319966f37458fef8f4e244e/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/webdevstar/react-native-snap-carousel/8f65a9af47c7943d5319966f37458fef8f4e244e/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/webdevstar/react-native-snap-carousel/8f65a9af47c7943d5319966f37458fef8f4e244e/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/webdevstar/react-native-snap-carousel/8f65a9af47c7943d5319966f37458fef8f4e244e/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | example
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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/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/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/react-native-snap-carousel/8f65a9af47c7943d5319966f37458fef8f4e244e/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/keystores/BUCK:
--------------------------------------------------------------------------------
1 | keystore(
2 | name = "debug",
3 | properties = "debug.keystore.properties",
4 | store = "debug.keystore",
5 | visibility = [
6 | "PUBLIC",
7 | ],
8 | )
--------------------------------------------------------------------------------
/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/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'example'
2 | include ':react-native-linear-gradient'
3 | project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
4 |
5 | include ':app'
6 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "displayName": "example"
4 | }
--------------------------------------------------------------------------------
/example/index.android.js:
--------------------------------------------------------------------------------
1 | import { AppRegistry } from 'react-native';
2 | import Root from './src/index';
3 |
4 | AppRegistry.registerComponent('example', () => Root);
5 |
--------------------------------------------------------------------------------
/example/index.ios.js:
--------------------------------------------------------------------------------
1 | import { AppRegistry } from 'react-native';
2 | import Root from './src/index';
3 |
4 | AppRegistry.registerComponent('example', () => Root);
5 |
--------------------------------------------------------------------------------
/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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/example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | fr_FR
7 | CFBundleDisplayName
8 | example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0.0
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | imgur.com
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 | NSIncludesSubdomains
36 |
37 |
38 | localhost
39 |
40 | NSExceptionAllowsInsecureHTTPLoads
41 |
42 |
43 |
44 |
45 | NSLocationWhenInUseUsageDescription
46 |
47 | UILaunchStoryboardName
48 | LaunchScreen
49 | UIRequiredDeviceCapabilities
50 |
51 | armv7
52 |
53 | UIStatusBarStyle
54 | UIStatusBarStyleLightContent
55 | UISupportedInterfaceOrientations
56 |
57 | UIInterfaceOrientationPortrait
58 |
59 | UISupportedInterfaceOrientations~ipad
60 |
61 | UIInterfaceOrientationPortrait
62 |
63 | UIViewControllerBasedStatusBarAppearance
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/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/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/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/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "0.4.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start"
7 | },
8 | "dependencies": {
9 | "react": "16.0.0-alpha.12",
10 | "react-native": "~0.47.1",
11 | "react-native-linear-gradient": "^2.1.0",
12 | "react-native-snap-carousel": "file:../"
13 | },
14 | "devDependencies": {
15 | "babel-preset-react-native": "1.9.1"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/src/components/SliderEntry.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { View, Text, Image, TouchableOpacity } from 'react-native';
3 | import { ParallaxImage } from 'react-native-snap-carousel';
4 | import styles from 'example/src/styles/SliderEntry.style';
5 |
6 | export default class SliderEntry extends Component {
7 |
8 | static propTypes = {
9 | data: PropTypes.object.isRequired,
10 | even: PropTypes.bool,
11 | parallax: PropTypes.bool,
12 | parallaxProps: PropTypes.object
13 | };
14 |
15 | get image () {
16 | const { data: { illustration }, parallax, parallaxProps, even } = this.props;
17 |
18 | return parallax ? (
19 |
28 | ) : (
29 |
33 | );
34 | }
35 |
36 | render () {
37 | const { data: { title, subtitle }, even } = this.props;
38 |
39 | const uppercaseTitle = title ? (
40 |
44 | { title.toUpperCase() }
45 |
46 | ) : false;
47 |
48 | return (
49 | { alert(`You've clicked '${title}'`); }}
53 | >
54 |
55 | { this.image }
56 |
57 |
58 |
59 | { uppercaseTitle }
60 |
64 | { subtitle }
65 |
66 |
67 |
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, ScrollView, Text, StatusBar, Platform } from 'react-native';
3 | import LinearGradient from 'react-native-linear-gradient';
4 | import Carousel, { Pagination } from 'react-native-snap-carousel';
5 | import { sliderWidth, itemWidth } from 'example/src/styles/SliderEntry.style';
6 | import SliderEntry from 'example/src/components/SliderEntry';
7 | import styles, { colors } from 'example/src/styles/index.style';
8 | import { ENTRIES1, ENTRIES2 } from 'example/src/static/entries';
9 |
10 | const SLIDER_1_FIRST_ITEM = 1;
11 |
12 | export default class example extends Component {
13 |
14 | constructor (props) {
15 | super(props);
16 | this.state = {
17 | slider1ActiveSlide: SLIDER_1_FIRST_ITEM
18 | };
19 | }
20 |
21 | _renderItem ({item, index}) {
22 | return (
23 |
27 | );
28 | }
29 |
30 | _renderItemWithParallax ({item, index}, parallaxProps) {
31 | return (
32 |
38 | );
39 | }
40 |
41 | get example1 () {
42 | const { slider1ActiveSlide } = this.state;
43 |
44 | return (
45 |
46 | Example 1
47 | No momentum | Parallax | Pagination | Scale | Opacity
48 | this.setState({ slider1ActiveSlide: index }) }
62 | />
63 |
71 |
72 | );
73 | }
74 |
75 | get example2 () {
76 | return (
77 |
78 | Example 2
79 | Momentum | Left-aligned | Autoplay
80 |
96 |
97 | );
98 | }
99 |
100 | get gradient () {
101 | return (
102 |
108 | );
109 | }
110 |
111 | render () {
112 | return (
113 |
114 |
119 | { this.gradient }
120 |
127 | { this.example1 }
128 | { this.example2 }
129 |
130 |
131 | );
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/example/src/static/entries.js:
--------------------------------------------------------------------------------
1 | export const ENTRIES1 = [
2 | {
3 | title: 'Beautiful and dramatic Antelope Canyon',
4 | subtitle: 'Lorem ipsum dolor sit amet et nuncat mergitur',
5 | illustration: 'http://i.imgur.com/UYiroysl.jpg'
6 | },
7 | {
8 | title: 'Earlier this morning, NYC',
9 | subtitle: 'Lorem ipsum dolor sit amet',
10 | illustration: 'http://i.imgur.com/UPrs1EWl.jpg'
11 | },
12 | {
13 | title: 'White Pocket Sunset',
14 | subtitle: 'Lorem ipsum dolor sit amet et nuncat ',
15 | illustration: 'http://i.imgur.com/MABUbpDl.jpg'
16 | },
17 | {
18 | title: 'Acrocorinth, Greece',
19 | subtitle: 'Lorem ipsum dolor sit amet et nuncat mergitur',
20 | illustration: 'http://i.imgur.com/KZsmUi2l.jpg'
21 | },
22 | {
23 | title: 'The lone tree, majestic landscape of New Zealand',
24 | subtitle: 'Lorem ipsum dolor sit amet',
25 | illustration: 'http://i.imgur.com/2nCt3Sbl.jpg'
26 | },
27 | {
28 | title: 'Middle Earth, Germany',
29 | subtitle: 'Lorem ipsum dolor sit amet',
30 | illustration: 'http://i.imgur.com/lceHsT6l.jpg'
31 | }
32 | ];
33 |
34 | export const ENTRIES2 = [
35 | {
36 | title: 'Favourites landscapes',
37 | subtitle: 'Lorem ipsum dolor sit amet',
38 | illustration: 'http://i.imgur.com/SsJmZ9jl.jpg'
39 | },
40 | {
41 | title: 'Favourites landscapes',
42 | subtitle: 'Lorem ipsum dolor sit amet et nuncat mergitur',
43 | illustration: 'http://i.imgur.com/5tj6S7Ol.jpg'
44 | },
45 | {
46 | title: 'Favourites landscapes',
47 | subtitle: 'Lorem ipsum dolor sit amet et nuncat',
48 | illustration: 'http://i.imgur.com/pmSqIFZl.jpg'
49 | },
50 | {
51 | title: 'Favourites landscapes',
52 | subtitle: 'Lorem ipsum dolor sit amet et nuncat mergitur',
53 | illustration: 'http://i.imgur.com/cA8zoGel.jpg'
54 | },
55 | {
56 | title: 'Favourites landscapes',
57 | subtitle: 'Lorem ipsum dolor sit amet',
58 | illustration: 'http://i.imgur.com/pewusMzl.jpg'
59 | },
60 | {
61 | title: 'Favourites landscapes',
62 | subtitle: 'Lorem ipsum dolor sit amet et nuncat',
63 | illustration: 'http://i.imgur.com/l49aYS3l.jpg'
64 | }
65 | ];
66 |
--------------------------------------------------------------------------------
/example/src/styles/SliderEntry.style.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet, Dimensions, Platform } from 'react-native';
2 | import { colors } from 'example/src/styles/index.style';
3 |
4 | const { width: viewportWidth, height: viewportHeight } = Dimensions.get('window');
5 |
6 | function wp (percentage) {
7 | const value = (percentage * viewportWidth) / 100;
8 | return Math.round(value);
9 | }
10 |
11 | const slideHeight = viewportHeight * 0.4;
12 | const slideWidth = wp(75);
13 | const itemHorizontalMargin = wp(2);
14 |
15 | export const sliderWidth = viewportWidth;
16 | export const itemWidth = slideWidth + itemHorizontalMargin * 2;
17 |
18 | const entryBorderRadius = 8;
19 |
20 | export default StyleSheet.create({
21 | slideInnerContainer: {
22 | width: itemWidth,
23 | height: slideHeight,
24 | paddingHorizontal: itemHorizontalMargin,
25 | paddingBottom: 18 // needed for shadow
26 | },
27 | imageContainer: {
28 | flex: 1,
29 | backgroundColor: 'white',
30 | borderTopLeftRadius: entryBorderRadius,
31 | borderTopRightRadius: entryBorderRadius
32 | },
33 | imageContainerEven: {
34 | backgroundColor: colors.black
35 | },
36 | image: {
37 | ...StyleSheet.absoluteFillObject,
38 | resizeMode: 'cover',
39 | borderRadius: Platform.OS === 'ios' ? entryBorderRadius : 0,
40 | borderTopLeftRadius: entryBorderRadius,
41 | borderTopRightRadius: entryBorderRadius
42 | },
43 | // image's border radius is buggy on ios; let's hack it!
44 | radiusMask: {
45 | position: 'absolute',
46 | bottom: 0,
47 | left: 0,
48 | right: 0,
49 | height: entryBorderRadius,
50 | backgroundColor: 'white'
51 | },
52 | radiusMaskEven: {
53 | backgroundColor: colors.black
54 | },
55 | textContainer: {
56 | justifyContent: 'center',
57 | paddingTop: 20 - entryBorderRadius,
58 | paddingBottom: 20,
59 | paddingHorizontal: 16,
60 | backgroundColor: 'white',
61 | borderBottomLeftRadius: entryBorderRadius,
62 | borderBottomRightRadius: entryBorderRadius
63 | },
64 | textContainerEven: {
65 | backgroundColor: colors.black
66 | },
67 | title: {
68 | color: colors.black,
69 | fontSize: 13,
70 | fontWeight: 'bold',
71 | letterSpacing: 0.5
72 | },
73 | titleEven: {
74 | color: 'white'
75 | },
76 | subtitle: {
77 | marginTop: 6,
78 | color: colors.gray,
79 | fontSize: 12,
80 | fontStyle: 'italic'
81 | },
82 | subtitleEven: {
83 | color: 'rgba(255, 255, 255, 0.7)'
84 | }
85 | });
86 |
--------------------------------------------------------------------------------
/example/src/styles/index.style.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | export const colors = {
4 | black: '#1a1917',
5 | gray: '#888888',
6 | background1: '#B721FF',
7 | background2: '#21D4FD'
8 | };
9 |
10 | export default StyleSheet.create({
11 | container: {
12 | flex: 1,
13 | backgroundColor: colors.background1
14 | },
15 | gradient: {
16 | ...StyleSheet.absoluteFillObject
17 | },
18 | scrollview: {
19 | flex: 1,
20 | paddingTop: 50
21 | },
22 | scrollviewContentContainer: {
23 | paddingBottom: 50
24 | },
25 | exampleContainer: {
26 | marginBottom: 30
27 | },
28 | title: {
29 | backgroundColor: 'transparent',
30 | color: 'rgba(255, 255, 255, 0.9)',
31 | fontSize: 20,
32 | fontWeight: 'bold',
33 | textAlign: 'center'
34 | },
35 | subtitle: {
36 | marginTop: 5,
37 | backgroundColor: 'transparent',
38 | color: 'rgba(255, 255, 255, 0.75)',
39 | fontSize: 13,
40 | fontStyle: 'italic',
41 | textAlign: 'center'
42 | },
43 | slider: {
44 | marginTop: 25
45 | },
46 | sliderContentContainer: {
47 | },
48 | paginationContainer: {
49 | paddingVertical: 8
50 | },
51 | paginationDot: {
52 | width: 8,
53 | height: 8,
54 | borderRadius: 4,
55 | marginHorizontal: 8,
56 | backgroundColor: 'rgba(255, 255, 255, 0.92)'
57 | }
58 | });
59 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-snap-carousel",
3 | "version": "3.0.0",
4 | "description": "Swiper component for React Native with previews, snapping effect, parallax images, performant handling of huge numbers of items, and RTL support. Compatible with Android & iOS.",
5 | "main": "src/index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "github.com/archriss/react-native-snap-carousel"
9 | },
10 | "keywords": [
11 | "react",
12 | "native",
13 | "carousel",
14 | "slider",
15 | "swiper",
16 | "flatlist",
17 | "scrollview",
18 | "parallax",
19 | "images",
20 | "infinite",
21 | "scroll",
22 | "scrolling",
23 | "items",
24 | "snap",
25 | "android",
26 | "ios",
27 | "snapping",
28 | "component",
29 | "rtl"
30 | ],
31 | "author": "Archriss (github.com/archriss)",
32 | "license": "ISC",
33 | "dependencies": {
34 | "lodash.debounce": "4.0.8",
35 | "prop-types": "^15.5.10",
36 | "react-addons-shallow-compare": "15.6.0"
37 | },
38 | "peerDependencies": {
39 | "react": "*",
40 | "react-native": "*"
41 | },
42 | "devDependencies": {
43 | "babel-eslint": "^7.2.3",
44 | "eslint": "^3.19.0",
45 | "eslint-config-standard": "^10.2.1",
46 | "eslint-config-standard-react": "^5.0.0",
47 | "eslint-plugin-import": "^2.3.0",
48 | "eslint-plugin-node": "^5.0.0",
49 | "eslint-plugin-promise": "^3.5.0",
50 | "eslint-plugin-react": "^7.0.1",
51 | "eslint-plugin-standard": "^3.0.1"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/carousel/Carousel.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, FlatList, Animated, Platform, Easing, I18nManager, ViewPropTypes } from 'react-native';
3 | import PropTypes from 'prop-types';
4 | import shallowCompare from 'react-addons-shallow-compare';
5 | import _debounce from 'lodash.debounce';
6 |
7 | // Native driver for scroll events
8 | // See: https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html
9 | const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
10 |
11 | // React Native automatically handles RTL layouts; unfortunately, it's buggy with horizontal ScrollView
12 | // See https://github.com/facebook/react-native/issues/11960
13 | // NOTE: the following variable is not declared in the constructor
14 | // otherwise it is undefined at init, which messes with custom indexes
15 | const IS_RTL = I18nManager.isRTL;
16 |
17 | export default class Carousel extends Component {
18 |
19 | static propTypes = {
20 | ...FlatList.propTypes,
21 | data: PropTypes.array.isRequired,
22 | renderItem: PropTypes.func.isRequired,
23 | itemWidth: PropTypes.number, // required for horizontal carousel
24 | itemHeight: PropTypes.number, // required for vertical carousel
25 | sliderWidth: PropTypes.number, // required for horizontal carousel
26 | sliderHeight: PropTypes.number, // required for vertical carousel
27 | activeSlideAlignment: PropTypes.oneOf(['center', 'end', 'start']),
28 | activeSlideOffset: PropTypes.number,
29 | animationFunc: PropTypes.string,
30 | animationOptions: PropTypes.object,
31 | apparitionDelay: PropTypes.number,
32 | autoplay: PropTypes.bool,
33 | autoplayDelay: PropTypes.number,
34 | autoplayInterval: PropTypes.number,
35 | containerCustomStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
36 | contentContainerCustomStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
37 | enableMomentum: PropTypes.bool,
38 | enableSnap: PropTypes.bool,
39 | firstItem: PropTypes.number,
40 | hasParallaxImages: PropTypes.bool,
41 | inactiveSlideOpacity: PropTypes.number,
42 | inactiveSlideScale: PropTypes.number,
43 | scrollEndDragDebounceValue: PropTypes.number,
44 | slideStyle: Animated.View.propTypes.style,
45 | shouldOptimizeUpdates: PropTypes.bool,
46 | snapOnAndroid: PropTypes.bool,
47 | swipeThreshold: PropTypes.number,
48 | useNativeOnScroll: PropTypes.bool,
49 | vertical: PropTypes.bool,
50 | onSnapToItem: PropTypes.func
51 | };
52 |
53 | static defaultProps = {
54 | activeSlideAlignment: 'center',
55 | activeSlideOffset: 25,
56 | animationFunc: 'timing',
57 | animationOptions: {
58 | duration: 600,
59 | easing: Easing.elastic(1)
60 | },
61 | apparitionDelay: 250,
62 | autoplay: false,
63 | autoplayDelay: 5000,
64 | autoplayInterval: 3000,
65 | containerCustomStyle: {},
66 | contentContainerCustomStyle: {},
67 | enableMomentum: false,
68 | enableSnap: true,
69 | firstItem: 0,
70 | hasParallaxImages: false,
71 | inactiveSlideOpacity: 0.7,
72 | inactiveSlideScale: 0.9,
73 | scrollEndDragDebounceValue: Platform.OS === 'ios' ? 50 : 150,
74 | slideStyle: {},
75 | shouldOptimizeUpdates: true,
76 | snapOnAndroid: true,
77 | swipeThreshold: 20,
78 | useNativeOnScroll: false,
79 | vertical: false
80 | }
81 |
82 | constructor (props) {
83 | super(props);
84 |
85 | const initialActiveItem = this._getFirstItem(props.firstItem);
86 | this.state = {
87 | activeItem: initialActiveItem,
88 | previousActiveItem: initialActiveItem, // used only when `enableMomentum` is set to `true`
89 | previousFirstItem: initialActiveItem,
90 | hideCarousel: true,
91 | interpolators: []
92 | };
93 |
94 | this._positions = [];
95 | this._currentContentOffset = 0; // store ScrollView's scroll position
96 | this._hasFiredEdgeItemCallback = true; // deal with overscroll and callback
97 | this._canFireCallback = false; // used only when `enableMomentum` is set to `false`
98 | this._isShortSnapping = false; // used only when `enableMomentum` is set to `false`
99 |
100 | this._initInterpolators = this._initInterpolators.bind(this);
101 | this._getItemLayout = this._getItemLayout.bind(this);
102 | this._renderItem = this._renderItem.bind(this);
103 | this._onScroll = this._onScroll.bind(this);
104 | this._onScrollEnd = this._snapEnabled || props.autoplay ? this._onScrollEnd.bind(this) : undefined;
105 | this._onScrollBeginDrag = this._snapEnabled ? this._onScrollBeginDrag.bind(this) : undefined;
106 | this._onScrollEndDrag = !props.enableMomentum ? this._onScrollEndDrag.bind(this) : undefined;
107 | this._onMomentumScrollEnd = props.enableMomentum ? this._onMomentumScrollEnd.bind(this) : undefined;
108 | this._onTouchStart = this._onTouchStart.bind(this);
109 | this._onTouchRelease = this._onTouchRelease.bind(this);
110 | this._onLayout = this._onLayout.bind(this);
111 | this._onSnap = this._onSnap.bind(this);
112 |
113 | // Native driver for scroll events
114 | if (props.useNativeOnScroll || props.hasParallaxImages || props.scrollEventThrottle < 16) {
115 | const scrollEventConfig = {
116 | listener: this._onScroll,
117 | useNativeDriver: true
118 | };
119 | this._scrollPos = new Animated.Value(0);
120 | this._onScrollHandler = props.vertical ?
121 | Animated.event(
122 | [{ nativeEvent: { contentOffset: { y: this._scrollPos } } }],
123 | scrollEventConfig
124 | ) : Animated.event(
125 | [{ nativeEvent: { contentOffset: { x: this._scrollPos } } }],
126 | scrollEventConfig
127 | );
128 | } else {
129 | this._onScrollHandler = this._onScroll;
130 | }
131 |
132 | // Debounce `_onScrollEndDrag` execution
133 | // This aims at improving snap feeling and callback reliability
134 | this._onScrollEndDragDebounced = !props.scrollEndDragDebounceValue ?
135 | this._onScrollEndDragDebounced.bind(this) :
136 | _debounce(
137 | this._onScrollEndDragDebounced,
138 | props.scrollEndDragDebounceValue,
139 | { leading: false, trailing: true }
140 | ).bind(this);
141 |
142 | // This bool aims at fixing an iOS bug due to scrollTo that triggers onMomentumScrollEnd.
143 | // onMomentumScrollEnd fires this._snapScroll, thus creating an infinite loop.
144 | this._ignoreNextMomentum = false;
145 |
146 | // Warnings
147 | if (!ViewPropTypes) {
148 | console.warn('react-native-snap-carousel: It is recommended to use at least version 0.44 of React Native with the plugin');
149 | }
150 | if (!props.vertical && (!props.sliderWidth || !props.itemWidth)) {
151 | console.warn('react-native-snap-carousel: You need to specify both `sliderWidth` and `itemWidth` for horizontal carousels');
152 | }
153 | if (props.vertical && (!props.sliderHeight || !props.itemHeight)) {
154 | console.warn('react-native-snap-carousel: You need to specify both `sliderHeight` and `itemHeight` for vertical carousels');
155 | }
156 | if (props.onScrollViewScroll) {
157 | console.warn('react-native-snap-carousel: Prop `onScrollViewScroll` has been removed. Use `onScroll` instead');
158 | }
159 | }
160 |
161 | componentDidMount () {
162 | const { firstItem, autoplay, apparitionDelay } = this.props;
163 | const _firstItem = this._getFirstItem(firstItem);
164 |
165 | this._initInterpolators(this.props, true);
166 |
167 | setTimeout(() => {
168 | this.snapToItem(_firstItem, false, false, true);
169 |
170 | if (autoplay) {
171 | this.startAutoplay();
172 | }
173 | }, 0);
174 |
175 | // hide FlatList's awful init
176 | setTimeout(() => {
177 | this.setState({ hideCarousel: false });
178 | }, apparitionDelay);
179 | }
180 |
181 | shouldComponentUpdate (nextProps, nextState) {
182 | if (this.props.shouldOptimizeUpdates === false) {
183 | return true;
184 | } else {
185 | return shallowCompare(this, nextProps, nextState);
186 | }
187 | }
188 |
189 | componentWillReceiveProps (nextProps) {
190 | const { activeItem, interpolators, previousFirstItem } = this.state;
191 | const { data, firstItem, sliderWidth, sliderHeight, itemWidth, itemHeight } = nextProps;
192 |
193 | const itemsLength = data.length;
194 | const nextFirstItem = this._getFirstItem(firstItem, nextProps);
195 | const nextActiveItem = activeItem || activeItem === 0 ? activeItem : nextFirstItem;
196 |
197 | const hasNewSliderWidth = sliderWidth && sliderWidth !== this.props.sliderWidth;
198 | const hasNewSliderHeight = sliderHeight && sliderHeight !== this.props.sliderHeight;
199 | const hasNewItemWidth = itemWidth && itemWidth !== this.props.itemWidth;
200 | const hasNewItemHeight = itemHeight && itemHeight !== this.props.itemHeight;
201 |
202 | if ((itemsLength && interpolators.length !== itemsLength) ||
203 | hasNewSliderWidth || hasNewSliderHeight || hasNewItemWidth || hasNewItemHeight) {
204 | this._positions = [];
205 | this._calcCardPositions(nextProps);
206 | this._initInterpolators(nextProps);
207 |
208 | this.setState({ activeItem: nextActiveItem });
209 |
210 | if (hasNewSliderWidth || hasNewSliderHeight || hasNewItemWidth || hasNewItemHeight ||
211 | (IS_RTL && !nextProps.vertical)) {
212 | this.snapToItem(nextActiveItem, false, false);
213 | }
214 | } else if (nextFirstItem !== previousFirstItem && nextFirstItem !== activeItem) {
215 | this.setState({
216 | previousFirstItem: nextFirstItem,
217 | activeItem: nextFirstItem
218 | });
219 | this.snapToItem(nextFirstItem);
220 | }
221 | }
222 |
223 | componentWillUnmount () {
224 | this.stopAutoplay();
225 | clearTimeout(this._enableAutoplayTimeout);
226 | clearTimeout(this._autoplayTimeout);
227 | clearTimeout(this._snapNoMomentumTimeout);
228 | clearTimeout(this._scrollToTimeout);
229 | }
230 |
231 | get _snapEnabled () {
232 | const { enableSnap, snapOnAndroid } = this.props;
233 | return enableSnap && (Platform.OS === 'ios' || snapOnAndroid);
234 | }
235 |
236 | get currentIndex () {
237 | return this.state.activeItem;
238 | }
239 |
240 | get currentScrollPosition () {
241 | return this._currentContentOffset;
242 | }
243 |
244 | _getCustomIndex (index, props = this.props) {
245 | const itemsLength = props.data && props.data.length;
246 |
247 | if (!itemsLength || (!index && index !== 0)) {
248 | return 0;
249 | }
250 |
251 | return IS_RTL && !props.vertical ?
252 | itemsLength - index - 1 :
253 | index;
254 | }
255 |
256 | _getFirstItem (index, props = this.props) {
257 | const itemsLength = props.data && props.data.length;
258 |
259 | if (!itemsLength || index > itemsLength - 1 || index < 0) {
260 | return 0;
261 | }
262 |
263 | return index;
264 | }
265 |
266 | _calcCardPositions (props = this.props) {
267 | const { data, itemWidth, itemHeight, vertical } = props;
268 | const sizeRef = vertical ? itemHeight : itemWidth;
269 |
270 | data.forEach((itemData, index) => {
271 | const _index = this._getCustomIndex(index, props);
272 | this._positions[index] = {
273 | start: _index * sizeRef,
274 | end: _index * sizeRef + sizeRef
275 | };
276 | });
277 | }
278 |
279 | _initInterpolators (props = this.props, initial = false) {
280 | const { activeItem } = this.state;
281 | const { data, firstItem } = props;
282 |
283 | let interpolators = [];
284 | const focusedItem = !initial && (activeItem || activeItem === 0) ?
285 | activeItem :
286 | this._getFirstItem(firstItem, props);
287 |
288 | data.forEach((itemData, index) => {
289 | const value = index === focusedItem ? 1 : 0;
290 | interpolators.push({
291 | opacity: new Animated.Value(value),
292 | scale: new Animated.Value(value)
293 | });
294 | });
295 | this.setState({ interpolators });
296 | }
297 |
298 | _getScrollOffset (event) {
299 | const { vertical } = this.props;
300 | return (event && event.nativeEvent && event.nativeEvent.contentOffset &&
301 | event.nativeEvent.contentOffset[vertical ? 'y' : 'x']) || 0;
302 | }
303 |
304 | _getActiveItem (offset) {
305 | const { activeSlideOffset } = this.props;
306 | const center = this._getCenter(offset);
307 |
308 | for (let i = 0; i < this._positions.length; i++) {
309 | const { start, end } = this._positions[i];
310 | if (center + activeSlideOffset >= start && center - activeSlideOffset <= end) {
311 | return i;
312 | }
313 | }
314 |
315 | const lastIndex = this._positions.length - 1;
316 | if (this._positions[lastIndex] && center - activeSlideOffset > this._positions[lastIndex].end) {
317 | return lastIndex;
318 | }
319 |
320 | return 0;
321 | }
322 |
323 | _getContainerInnerMargin (opposite = false) {
324 | const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
325 |
326 | if ((activeSlideAlignment === 'start' && !opposite) ||
327 | (activeSlideAlignment === 'end' && opposite)) {
328 | return 0;
329 | } else if ((activeSlideAlignment === 'end' && !opposite) ||
330 | (activeSlideAlignment === 'start' && opposite)) {
331 | return vertical ? sliderHeight - itemHeight : sliderWidth - itemWidth;
332 | } else {
333 | return vertical ? (sliderHeight - itemHeight) / 2 : (sliderWidth - itemWidth) / 2;
334 | }
335 | }
336 |
337 | _getCenter (offset) {
338 | const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
339 |
340 | let viewportOffset;
341 | if (activeSlideAlignment === 'start') {
342 | viewportOffset = vertical ? itemHeight / 2 : itemWidth / 2;
343 | } else if (activeSlideAlignment === 'end') {
344 | viewportOffset = vertical ?
345 | sliderHeight - (itemHeight / 2) :
346 | sliderWidth - (itemWidth / 2);
347 | } else {
348 | viewportOffset = vertical ? sliderHeight / 2 : sliderWidth / 2;
349 | }
350 |
351 | return offset + viewportOffset - (this._getContainerInnerMargin() * (IS_RTL ? -1 : 1));
352 | }
353 |
354 | _getKeyExtractor (item, index) {
355 | return `carousel-item-${index}`;
356 | }
357 |
358 | _getItemLayout (data, index) {
359 | const { itemWidth, itemHeight, vertical } = this.props;
360 | const itemSize = vertical ? itemHeight : itemWidth;
361 |
362 | return {
363 | length: itemSize,
364 | offset: itemSize * index,
365 | index
366 | };
367 | }
368 |
369 | _getItemOffset (index) {
370 | // 'viewPosition' doesn't work for the first item
371 | // It is always aligned to the left
372 | // Unfortunately, 'viewOffset' doesn't work on Android ATM
373 | if ((!IS_RTL && index === 0) ||
374 | (IS_RTL && index === this.props.data.length - 1)) {
375 | return this._getContainerInnerMargin();
376 | }
377 |
378 | return 0;
379 | }
380 |
381 | _getSlideAnimation (index, toValue) {
382 | const { animationFunc, animationOptions } = this.props;
383 | const animationCommonOptions = {
384 | isInteraction: false,
385 | useNativeDriver: true,
386 | ...animationOptions,
387 | toValue: toValue
388 | };
389 |
390 | return Animated.parallel([
391 | Animated['timing'](
392 | this.state.interpolators[index].opacity,
393 | { ...animationCommonOptions, easing: Easing.linear }
394 | ),
395 | Animated[animationFunc](
396 | this.state.interpolators[index].scale,
397 | { ...animationCommonOptions }
398 | )
399 | ]);
400 | }
401 |
402 | _onScroll (event) {
403 | const { activeItem } = this.state;
404 | const { data, enableMomentum, onScroll } = this.props;
405 |
406 | const scrollOffset = this._getScrollOffset(event);
407 | const newActiveItem = this._getActiveItem(scrollOffset);
408 | const itemsLength = data.length;
409 | let animations = [];
410 |
411 | this._currentContentOffset = scrollOffset;
412 |
413 | if (enableMomentum) {
414 | clearTimeout(this._snapNoMomentumTimeout);
415 | }
416 |
417 | if (activeItem !== newActiveItem) {
418 | if (activeItem === 0 || activeItem === itemsLength - 1) {
419 | this._hasFiredEdgeItemCallback = false;
420 | }
421 |
422 | // WARNING: `setState()` is asynchronous
423 | this.setState({ activeItem: newActiveItem }, () => {
424 | // When "short snapping", we can rely on the "activeItem/newActiveItem" comparison
425 | if (!enableMomentum && this._canFireCallback && this._isShortSnapping) {
426 | this._isShortSnapping = false;
427 | this._onSnap(newActiveItem);
428 | }
429 | });
430 |
431 | // With dynamically removed items, `activeItem` and
432 | // `newActiveItem`'s interpolators might be `undefined`
433 | if (this.state.interpolators[activeItem]) {
434 | animations.push(this._getSlideAnimation(activeItem, 0));
435 | }
436 | if (this.state.interpolators[newActiveItem]) {
437 | animations.push(this._getSlideAnimation(newActiveItem, 1));
438 | }
439 | Animated.parallel(animations, { stopTogether: false }).start();
440 | }
441 |
442 | // When scrolling, we need to check that we are not "short snapping",
443 | // that the new slide is different from the very first one,
444 | // that we are scrolling to the relevant slide,
445 | // and that callback can be fired
446 | if (!enableMomentum && this._canFireCallback && !this._isShortSnapping &&
447 | (this._scrollStartActive !== newActiveItem || !this._hasFiredEdgeItemCallback) &&
448 | this._itemToSnapTo === newActiveItem) {
449 | this.setState({ activeItem: newActiveItem }, () => {
450 | this._onSnap(newActiveItem);
451 | });
452 | }
453 |
454 | if (onScroll) {
455 | onScroll(event);
456 | }
457 | }
458 |
459 | _onTouchStart () {
460 | // `onTouchStart` is fired even when `scrollEnabled` is set to `false`
461 | if (this.props.scrollEnabled !== false && this._autoplaying) {
462 | this.stopAutoplay();
463 | }
464 | }
465 |
466 | // Used when `enableSnap` is ENABLED
467 | _onScrollBeginDrag (event) {
468 | const { onScrollBeginDrag } = this.props;
469 |
470 | this._scrollStartOffset = this._getScrollOffset(event);
471 | this._scrollStartActive = this._getActiveItem(this._scrollStartOffset);
472 | this._ignoreNextMomentum = false;
473 | this._canFireCallback = false;
474 |
475 | if (onScrollBeginDrag) {
476 | onScrollBeginDrag(event);
477 | }
478 | }
479 |
480 | // Used when `enableMomentum` is DISABLED
481 | _onScrollEndDrag (event) {
482 | const { onScrollEndDrag } = this.props;
483 |
484 | // event.persist(); // See https://stackoverflow.com/a/24679479
485 | this._onScrollEndDragDebounced();
486 |
487 | if (onScrollEndDrag) {
488 | onScrollEndDrag(event);
489 | }
490 | }
491 |
492 | _onScrollEndDragDebounced (event) {
493 | if (this._flatlist && this._onScrollEnd) {
494 | this._onScrollEnd();
495 | }
496 | }
497 |
498 | // Used when `enableMomentum` is ENABLED
499 | _onMomentumScrollEnd (event) {
500 | const { onMomentumScrollEnd } = this.props;
501 |
502 | if (this._flatlist && this._onScrollEnd) {
503 | this._onScrollEnd();
504 | }
505 |
506 | if (onMomentumScrollEnd) {
507 | onMomentumScrollEnd(event);
508 | }
509 | }
510 |
511 | _onScrollEnd (event) {
512 | const { autoplay } = this.props;
513 |
514 | if (this._ignoreNextMomentum) {
515 | // iOS fix
516 | this._ignoreNextMomentum = false;
517 | return;
518 | }
519 |
520 | this._scrollEndOffset = this._currentContentOffset;
521 | this._scrollEndActive = this._getActiveItem(this._scrollEndOffset);
522 |
523 | if (this._snapEnabled) {
524 | const delta = this._scrollEndOffset - this._scrollStartOffset;
525 | this._snapScroll(delta);
526 | }
527 |
528 | if (autoplay) {
529 | // Restart autoplay after a little while
530 | // This could be done when releasing touch
531 | // but the event is buggy on Android...
532 | // https://github.com/facebook/react-native/issues/9439
533 | clearTimeout(this._enableAutoplayTimeout);
534 | this._enableAutoplayTimeout = setTimeout(() => {
535 | this.startAutoplay();
536 | }, 300);
537 | }
538 | }
539 |
540 | // Due to a bug, this event is only fired on iOS
541 | // https://github.com/facebook/react-native/issues/6791
542 | // it's fine since we're only fixing an iOS bug in it, so ...
543 | _onTouchRelease (event) {
544 | if (this.props.enableMomentum && Platform.OS === 'ios') {
545 | clearTimeout(this._snapNoMomentumTimeout);
546 | this._snapNoMomentumTimeout = setTimeout(() => {
547 | this.snapToItem(this.currentIndex);
548 | }, 100);
549 | }
550 | }
551 |
552 | _onLayout (event) {
553 | const { onLayout } = this.props;
554 |
555 | this._calcCardPositions();
556 | this.snapToItem(this.currentIndex, false, false);
557 |
558 | if (onLayout) {
559 | onLayout(event);
560 | }
561 | }
562 |
563 | _snapScroll (delta) {
564 | const { swipeThreshold, vertical } = this.props;
565 |
566 | // When using momentum and releasing the touch with
567 | // no velocity, scrollEndActive will be undefined (iOS)
568 | if (!this._scrollEndActive && this._scrollEndActive !== 0 && Platform.OS === 'ios') {
569 | this._scrollEndActive = this._scrollStartActive;
570 | }
571 |
572 | if (this._scrollStartActive !== this._scrollEndActive) {
573 | // Flag necessary in order to fire the callback
574 | // at the right time in `_onScroll()`
575 | this._isShortSnapping = false;
576 |
577 | // Snap to the new active item
578 | this.snapToItem(this._scrollEndActive);
579 | } else {
580 | this._isShortSnapping = true;
581 |
582 | // Snap depending on delta
583 | if (delta > 0) {
584 | if (delta > swipeThreshold) {
585 | if (IS_RTL && !vertical) {
586 | this.snapToItem(this._scrollStartActive - 1);
587 | } else {
588 | this.snapToItem(this._scrollStartActive + 1);
589 | }
590 | } else {
591 | this.snapToItem(this._scrollEndActive);
592 | }
593 | } else if (delta < 0) {
594 | if (delta < -swipeThreshold) {
595 | if (IS_RTL && !vertical) {
596 | this.snapToItem(this._scrollStartActive + 1);
597 | } else {
598 | this.snapToItem(this._scrollStartActive - 1);
599 | }
600 | } else {
601 | this.snapToItem(this._scrollEndActive);
602 | }
603 | } else {
604 | // Snap to current
605 | this.snapToItem(this._scrollEndActive);
606 | }
607 | }
608 | }
609 |
610 | _onSnap (index) {
611 | const { data, enableMomentum, onSnapToItem } = this.props;
612 | const itemsLength = data.length;
613 |
614 | if (this._flatlist) {
615 | if (enableMomentum) {
616 | onSnapToItem && onSnapToItem(index);
617 | } else if (this._canFireCallback) {
618 | this._canFireCallback = false;
619 |
620 | if (index === 0 || index === itemsLength - 1) {
621 | this._hasFiredEdgeItemCallback = true;
622 | }
623 |
624 | onSnapToItem && onSnapToItem(index);
625 | }
626 | }
627 | }
628 |
629 | startAutoplay () {
630 | const { autoplayInterval, autoplayDelay } = this.props;
631 |
632 | if (this._autoplaying) {
633 | return;
634 | }
635 |
636 | clearTimeout(this._autoplayTimeout);
637 | this._autoplayTimeout = setTimeout(() => {
638 | this._autoplaying = true;
639 | this._autoplayInterval = setInterval(() => {
640 | if (this._autoplaying) {
641 | this.snapToNext();
642 | }
643 | }, autoplayInterval);
644 | }, autoplayDelay);
645 | }
646 |
647 | stopAutoplay () {
648 | this._autoplaying = false;
649 | clearInterval(this._autoplayInterval);
650 | }
651 |
652 | snapToItem (index, animated = true, fireCallback = true, initial = false) {
653 | const { previousActiveItem } = this.state;
654 | const { data, enableMomentum, scrollEndDragDebounceValue } = this.props;
655 | const itemsLength = data.length;
656 |
657 | if (!itemsLength) {
658 | return;
659 | }
660 |
661 | if (!index) {
662 | index = 0;
663 | }
664 |
665 | if (itemsLength > 0 && index >= itemsLength) {
666 | index = itemsLength - 1;
667 | this._isShortSnapping = false; // prevent issue #105
668 | if (this._scrollStartActive === itemsLength - 1 && this._hasFiredEdgeItemCallback) {
669 | fireCallback = false;
670 | }
671 | } else if (index < 0) {
672 | index = 0;
673 | this._isShortSnapping = false; // prevent issue #105
674 | if (this._scrollStartActive === 0 && this._hasFiredEdgeItemCallback) {
675 | fireCallback = false;
676 | }
677 | } else if (enableMomentum && index === previousActiveItem) {
678 | fireCallback = false;
679 | }
680 |
681 | // Make sure the component hasn't been unmounted
682 | if (this._flatlist) {
683 | if (enableMomentum) {
684 | this.setState({ previousActiveItem: index });
685 | // Callback can be fired here when relying on 'onMomentumScrollEnd'
686 | if (fireCallback) {
687 | this._onSnap(index);
688 | }
689 | } else {
690 | // `_onScrollEndDragDebounced()` might occur when "peaking" to another item
691 | // Therefore we need to make sure that callback is fired when scrolling
692 | // back to the right one
693 | this._itemToSnapTo = index;
694 |
695 | // Callback needs to be fired while scrolling when relying on 'onScrollEndDrag'
696 | // Thus we need a flag on top of the debounce function to call it only once
697 | this._canFireCallback = this.props.onSnapToItem && fireCallback;
698 |
699 | // If user has scrolled to an edge item before the end of `scrollEndDragDebounceValue`
700 | // `onScroll()` won't be triggered and callback is not going to be fired
701 | // So we check if scroll position has been updated after a small delay and,
702 | // if not, it's safe to assume that callback should be called
703 | const scrollPosition = this._currentContentOffset;
704 | clearTimeout(this._scrollToTimeout);
705 | this._scrollToTimeout = setTimeout(() => {
706 | if (scrollPosition === this._currentContentOffset && this._canFireCallback) {
707 | this._onSnap(index);
708 | }
709 | }, Math.max(500, scrollEndDragDebounceValue + 50));
710 | }
711 |
712 | // Unfortunately, 'viewPosition' is quite buggy at the moment
713 | // Moreover, 'viewOffset' just doesn't work on Android
714 | // const viewOffset = this._getItemOffset(index);
715 | // let viewPosition = 0.5;
716 | // if (activeSlideAlignment === 'start') {
717 | // viewPosition = IS_RTL ? 1 : 0;
718 | // } else if (activeSlideAlignment === 'end') {
719 | // viewPosition = IS_RTL ? 0 : 1;
720 | // }
721 |
722 | this._flatlist.scrollToIndex({
723 | index,
724 | viewPosition: 0,
725 | viewOffset: 0,
726 | animated
727 | });
728 |
729 | // iOS fix, check the note in the constructor
730 | if (!initial && Platform.OS === 'ios') {
731 | this._ignoreNextMomentum = true;
732 | }
733 | }
734 | }
735 |
736 | snapToNext (animated = true) {
737 | const itemsLength = this.props.data.length;
738 |
739 | let newIndex = this.currentIndex + 1;
740 | if (newIndex > itemsLength - 1) {
741 | newIndex = 0;
742 | }
743 | this.snapToItem(newIndex, animated);
744 | }
745 |
746 | snapToPrev (animated = true) {
747 | const itemsLength = this.props.data.length;
748 |
749 | let newIndex = this.currentIndex - 1;
750 | if (newIndex < 0) {
751 | newIndex = itemsLength - 1;
752 | }
753 | this.snapToItem(newIndex, animated);
754 | }
755 |
756 | _renderItem ({ item, index }) {
757 | const { interpolators } = this.state;
758 | const {
759 | renderItem,
760 | sliderWidth,
761 | sliderHeight,
762 | itemWidth,
763 | itemHeight,
764 | slideStyle,
765 | inactiveSlideScale,
766 | inactiveSlideOpacity,
767 | vertical,
768 | hasParallaxImages
769 | } = this.props;
770 |
771 | const animatedValue = interpolators && interpolators[index];
772 |
773 | if (!animatedValue || !animatedValue.opacity || !animatedValue.scale) {
774 | return false;
775 | }
776 |
777 | const animatedStyle = {
778 | opacity: animatedValue.opacity.interpolate({
779 | inputRange: [0, 1],
780 | outputRange: [inactiveSlideOpacity, 1]
781 | }),
782 | transform: [{
783 | scale: animatedValue.scale.interpolate({
784 | inputRange: [0, 1],
785 | outputRange: [inactiveSlideScale, 1]
786 | })
787 | }]
788 | };
789 |
790 | const parallaxProps = hasParallaxImages ? {
791 | scrollPosition: this._scrollPos,
792 | carouselRef: this._flatlist,
793 | vertical,
794 | sliderWidth,
795 | sliderHeight,
796 | itemWidth,
797 | itemHeight
798 | } : undefined;
799 |
800 | return (
801 |
802 | { renderItem({ item, index }, parallaxProps) }
803 |
804 | );
805 | }
806 |
807 | render () {
808 | const { hideCarousel } = this.state;
809 | const {
810 | containerCustomStyle,
811 | contentContainerCustomStyle,
812 | data,
813 | enableMomentum,
814 | firstItem,
815 | hasParallaxImages,
816 | itemWidth,
817 | itemHeight,
818 | keyExtractor,
819 | renderItem,
820 | sliderWidth,
821 | sliderHeight,
822 | useNativeOnScroll,
823 | vertical
824 | } = this.props;
825 |
826 | if (!data || !renderItem) {
827 | return false;
828 | }
829 |
830 | const wrapList = useNativeOnScroll || hasParallaxImages;
831 | const Component = wrapList ? AnimatedFlatList : FlatList;
832 |
833 | const style = [
834 | containerCustomStyle || {},
835 | hideCarousel ? { opacity: 0 } : {},
836 | vertical ?
837 | { height: sliderHeight, flexDirection: 'column' } :
838 | // LTR hack; see https://github.com/facebook/react-native/issues/11960
839 | { width: sliderWidth, flexDirection: IS_RTL ? 'row-reverse' : 'row' }
840 | ];
841 | const contentContainerStyle = [
842 | contentContainerCustomStyle || {},
843 | vertical ? {
844 | paddingTop: this._getContainerInnerMargin(),
845 | paddingBottom: this._getContainerInnerMargin(true)
846 | } : {
847 | paddingLeft: this._getContainerInnerMargin(),
848 | paddingRight: this._getContainerInnerMargin(true)
849 | }
850 | ];
851 |
852 | const visibleItems = Math.ceil(vertical ?
853 | sliderHeight / itemHeight :
854 | sliderWidth / itemWidth) + 1;
855 |
856 | return (
857 | { if (c) { this._flatlist = wrapList ? c._component : c; } }}
870 | data={data}
871 | renderItem={this._renderItem}
872 | // extraData={this.state}
873 | getItemLayout={this._getItemLayout}
874 | keyExtractor={keyExtractor || this._getKeyExtractor}
875 | initialScrollIndex={firstItem || undefined}
876 | numColumns={1}
877 | style={style}
878 | contentContainerStyle={contentContainerStyle}
879 | horizontal={!vertical}
880 | onScroll={this._onScrollHandler}
881 | onScrollBeginDrag={this._onScrollBeginDrag}
882 | onScrollEndDrag={this._onScrollEndDrag}
883 | onMomentumScrollEnd={this._onMomentumScrollEnd}
884 | onResponderRelease={this._onTouchRelease}
885 | onTouchStart={this._onTouchStart}
886 | onLayout={this._onLayout}
887 | />
888 | );
889 | }
890 | }
891 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Carousel from './carousel/Carousel';
2 | import Pagination from './pagination/Pagination';
3 | import ParallaxImage from './parallaximage/ParallaxImage';
4 |
5 | export { Carousel as default, Pagination, ParallaxImage };
6 |
--------------------------------------------------------------------------------
/src/pagination/Pagination.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, ViewPropTypes } from 'react-native';
3 | import PropTypes from 'prop-types';
4 | import PaginationDot from './PaginationDot';
5 | import styles from './Pagination.style';
6 |
7 | export default class Pagination extends Component {
8 |
9 | static propTypes = {
10 | dotsLength: PropTypes.number.isRequired,
11 | activeDotIndex: PropTypes.number.isRequired,
12 | containerStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
13 | dotStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
14 | inactiveDotStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
15 | inactiveDotOpacity: PropTypes.number,
16 | inactiveDotScale: PropTypes.number
17 | };
18 |
19 | get dots () {
20 | const {
21 | dotsLength,
22 | activeDotIndex,
23 | dotStyle,
24 | inactiveDotStyle,
25 | inactiveDotOpacity,
26 | inactiveDotScale
27 | } = this.props;
28 |
29 | let dots = [];
30 |
31 | for (let i = 0; i < dotsLength; i++) {
32 | dots.push(
33 |
41 | );
42 | }
43 |
44 | return dots;
45 | }
46 |
47 | render () {
48 | const { dotsLength, containerStyle } = this.props;
49 |
50 | if (!dotsLength || dotsLength < 2) {
51 | return false;
52 | }
53 |
54 | return (
55 |
59 | { this.dots }
60 |
61 | );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/pagination/Pagination.style.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | const DEFAULT_DOT_SIZE = 7;
4 | const DEFAULT_DOT_COLOR = 'rgba(0, 0, 0, 0.75)';
5 |
6 | export default StyleSheet.create({
7 | sliderPagination: {
8 | flexDirection: 'row',
9 | alignItems: 'center',
10 | justifyContent: 'center',
11 | paddingHorizontal: 20,
12 | paddingVertical: 30
13 | },
14 | sliderPaginationDot: {
15 | width: DEFAULT_DOT_SIZE,
16 | height: DEFAULT_DOT_SIZE,
17 | borderRadius: DEFAULT_DOT_SIZE / 2,
18 | marginHorizontal: 8,
19 | backgroundColor: DEFAULT_DOT_COLOR
20 | }
21 | });
22 |
--------------------------------------------------------------------------------
/src/pagination/PaginationDot.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, Animated, Easing, ViewPropTypes } from 'react-native';
3 | import PropTypes from 'prop-types';
4 | import styles from './Pagination.style';
5 |
6 | export default class PaginationDot extends Component {
7 |
8 | static propTypes = {
9 | active: PropTypes.bool,
10 | style: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
11 | inactiveStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
12 | inactiveOpacity: PropTypes.number,
13 | inactiveScale: PropTypes.number
14 | };
15 |
16 | static defaultProps = {
17 | inactiveOpacity: 0.5,
18 | inactiveScale: 0.5
19 | }
20 |
21 | constructor (props) {
22 | super(props);
23 | this.state = {
24 | animOpacity: new Animated.Value(0),
25 | animTransform: new Animated.Value(0)
26 | };
27 | }
28 |
29 | componentDidMount () {
30 | if (this.props.active) {
31 | this._animate(1);
32 | }
33 | }
34 |
35 | componentWillReceiveProps (nextProps) {
36 | if (nextProps.active !== this.props.active) {
37 | this._animate(nextProps.active ? 1 : 0);
38 | }
39 | }
40 |
41 | _animate (toValue = 0) {
42 | const { animOpacity, animTransform } = this.state;
43 |
44 | Animated.parallel([
45 | Animated.timing(animOpacity, {
46 | toValue,
47 | duration: 250,
48 | easing: Easing.linear,
49 | isInteraction: false,
50 | useNativeDriver: true
51 | }),
52 | Animated.spring(animTransform, {
53 | toValue,
54 | friction: 4,
55 | tension: 50,
56 | isInteraction: false,
57 | useNativeDriver: true
58 | })
59 | ]).start();
60 | }
61 |
62 | render () {
63 | const { animOpacity, animTransform } = this.state;
64 | const { active, style, inactiveStyle, inactiveOpacity, inactiveScale } = this.props;
65 |
66 | const animatedStyle = {
67 | opacity: animOpacity.interpolate({
68 | inputRange: [0, 1],
69 | outputRange: [inactiveOpacity, 1]
70 | }),
71 | transform: [{
72 | scale: animTransform.interpolate({
73 | inputRange: [0, 1],
74 | outputRange: [inactiveScale, 1]
75 | })
76 | }]
77 | };
78 | const dotStyle = [
79 | styles.sliderPaginationDot,
80 | style || {},
81 | (!active && inactiveStyle) || {},
82 | animatedStyle
83 | ];
84 |
85 | return (
86 |
87 | );
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/pagination/README.md:
--------------------------------------------------------------------------------
1 | # `` component
2 |
3 | Starting with version `2.4.0`, a customizable `` component has been added. This is how it looks like with its default configuration:
4 |
5 | 
6 |
7 | ## Props
8 |
9 | Prop | Description | Type | Default
10 | ------ | ------ | ------ | ------
11 | dotsLength | Number of dots to display | Number | **Required**
12 | activeDotIndex | Currently focused dot | Number | **Required**
13 | containerStyle | Style for dots' container that will be merged with the default one | View Style Object | `{}`
14 | dotStyle | Dots' style that will be merged with the default one | View Style Object | `{}`
15 | inactiveDotStyle | Dots' style that will be applied to inactive elements | View Style Object | `{}`
16 | inactiveDotOpacity | Value of the opacity effect applied to inactive dots | Number | `0.5`
17 | inactiveDotScale | Value of the 'scale' transform applied to inactive dots | Number | `0.5`
18 |
19 | ## Usage
20 |
21 | Since `` is, purposely, a separated component, you need to connect it to your `` component manually. This is pretty straightforward, but here is an example to get you started.
22 |
23 | ```javascript
24 | import Carousel, { Pagination } from 'react-native-snap-carousel';
25 |
26 | export default class MyCarousel extends Component {
27 |
28 | _renderItem ({item, index}) {
29 | return
30 | }
31 |
32 | get pagination () {
33 | const { entries, activeSlide } = this.state;
34 | return (
35 |
52 | );
53 | }
54 |
55 | render () {
56 | return (
57 |
58 | this.setState({ activeSlide: index }) }
62 | />
63 | { this.pagination }
64 |
65 | );
66 | }
67 | ```
68 |
--------------------------------------------------------------------------------
/src/parallaximage/ParallaxImage.js:
--------------------------------------------------------------------------------
1 | // Parallax effect inspired by https://github.com/oblador/react-native-parallax/
2 |
3 | import React, { Component } from 'react';
4 | import { View, ViewPropTypes, Image, Animated, Easing, ActivityIndicator, findNodeHandle } from 'react-native';
5 | import PropTypes from 'prop-types';
6 | import styles from './ParallaxImage.style';
7 |
8 | export default class ParallaxImage extends Component {
9 |
10 | static propTypes = {
11 | ...Image.propTypes,
12 | carouselRef: PropTypes.object, // passed from
13 | itemHeight: PropTypes.number, // passed from
14 | itemWidth: PropTypes.number, // passed from
15 | scrollPosition: PropTypes.object, // passed from
16 | sliderHeight: PropTypes.number, // passed from
17 | sliderWidth: PropTypes.number, // passed from
18 | vertical: PropTypes.bool, // passed from
19 | containerStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style,
20 | dimensions: PropTypes.shape({
21 | width: PropTypes.number,
22 | height: PropTypes.number
23 | }),
24 | fadeDuration: PropTypes.number,
25 | parallaxFactor: PropTypes.number,
26 | showSpinner: PropTypes.bool,
27 | spinnerColor: PropTypes.string
28 | };
29 |
30 | static defaultProps = {
31 | containerStyle: {},
32 | fadeDuration: 500,
33 | parallaxFactor: 0.3,
34 | showSpinner: true,
35 | spinnerColor: 'rgba(0, 0, 0, 0.4)'
36 | }
37 |
38 | constructor (props) {
39 | super(props);
40 | this.state = {
41 | offset: 0,
42 | width: 0,
43 | height: 0,
44 | status: 1, // 1 -> loading; 2 -> loaded // 3 -> transition finished; 4 -> error
45 | animOpacity: new Animated.Value(0)
46 | };
47 | this._onLoad = this._onLoad.bind(this);
48 | this._onError = this._onError.bind(this);
49 | }
50 |
51 | setNativeProps (nativeProps) {
52 | this._container.setNativeProps(nativeProps);
53 | }
54 |
55 | componentDidMount () {
56 | this._mounted = true;
57 |
58 | setTimeout(() => {
59 | this._measureLayout();
60 | }, 0);
61 | }
62 |
63 | componentWillUnmount () {
64 | this._mounted = false;
65 | }
66 |
67 | _measureLayout () {
68 | if (this._container) {
69 | const {
70 | dimensions,
71 | vertical,
72 | carouselRef,
73 | sliderWidth,
74 | sliderHeight,
75 | itemWidth,
76 | itemHeight
77 | } = this.props;
78 |
79 | if (carouselRef) {
80 | this._container.measureLayout(
81 | findNodeHandle(carouselRef),
82 | (x, y, width, height, pageX, pageY) => {
83 | const offset = vertical ?
84 | y - ((sliderHeight - itemHeight) / 2) :
85 | x - ((sliderWidth - itemWidth) / 2);
86 |
87 | this.setState({
88 | offset: offset,
89 | width: dimensions && dimensions.width ?
90 | dimensions.width :
91 | Math.ceil(width),
92 | height: dimensions && dimensions.height ?
93 | dimensions.height :
94 | Math.ceil(height)
95 | });
96 | }
97 | );
98 | }
99 | }
100 | }
101 |
102 | _onLoad (event) {
103 | const { animOpacity } = this.state;
104 | const { fadeDuration, onLoad } = this.props;
105 |
106 | if (!this._mounted) {
107 | return;
108 | }
109 |
110 | this.setState({ status: 2 });
111 |
112 | if (onLoad) {
113 | onLoad(event);
114 | }
115 |
116 | Animated.timing(animOpacity, {
117 | toValue: 1,
118 | duration: fadeDuration,
119 | easing: Easing.out(Easing.quad),
120 | isInteraction: false,
121 | useNativeDriver: true
122 | }).start(() => {
123 | this.setState({ status: 3 });
124 | });
125 | }
126 |
127 | // If arg is missing from method signature, it just won't be called
128 | _onError (event) {
129 | const { onError } = this.props;
130 |
131 | this.setState({ status: 4 });
132 |
133 | if (onError) {
134 | onError(event);
135 | }
136 | }
137 |
138 | get image () {
139 | const { status, animOpacity, offset, width, height } = this.state;
140 | const {
141 | scrollPosition,
142 | dimensions,
143 | vertical,
144 | sliderWidth,
145 | sliderHeight,
146 | parallaxFactor,
147 | style,
148 | ...other
149 | } = this.props;
150 |
151 | const parallaxPadding = (vertical ? height : width) * parallaxFactor;
152 | const dynamicStyles = {
153 | width: vertical ? width : width + parallaxPadding * 2,
154 | height: vertical ? height + parallaxPadding * 2 : height,
155 | opacity: animOpacity,
156 | transform: scrollPosition ? [
157 | {
158 | translateX: !vertical ? scrollPosition.interpolate({
159 | inputRange: [offset - sliderWidth, offset + sliderWidth],
160 | outputRange: [-parallaxPadding, parallaxPadding],
161 | extrapolate: 'clamp'
162 | }) : 0
163 | },
164 | {
165 | translateY: vertical ? scrollPosition.interpolate({
166 | inputRange: [offset - sliderHeight, offset + sliderHeight],
167 | outputRange: [-parallaxPadding, parallaxPadding],
168 | extrapolate: 'clamp'
169 | }) : 0
170 | }
171 | ] : []
172 | };
173 |
174 | return (
175 |
181 | );
182 | }
183 |
184 | get spinner () {
185 | const { status } = this.state;
186 | const { showSpinner, spinnerColor } = this.props;
187 |
188 | return status === 1 && showSpinner ? (
189 |
190 |
195 |
196 | ) : false;
197 | }
198 |
199 | render () {
200 | const { containerStyle } = this.props;
201 |
202 | return (
203 | { this._container = c; }}
205 | pointerEvents={'none'}
206 | style={[containerStyle, styles.container]}
207 | onLayout={this._measureLayout}
208 | >
209 | { this.image }
210 | { this.spinner }
211 |
212 | );
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/src/parallaximage/ParallaxImage.style.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | export default StyleSheet.create({
4 | container: {
5 | overflow: 'hidden',
6 | alignItems: 'center',
7 | justifyContent: 'center'
8 | },
9 | image: {
10 | position: 'relative',
11 | resizeMode: 'cover',
12 | width: null,
13 | height: null
14 | },
15 | loaderContainer: {
16 | ...StyleSheet.absoluteFillObject,
17 | alignItems: 'center',
18 | justifyContent: 'center'
19 | }
20 | });
21 |
--------------------------------------------------------------------------------
/src/parallaximage/README.md:
--------------------------------------------------------------------------------
1 | # `` component
2 |
3 | Version `3.0.0` introduced a `` component, an image component aware of carousel's current scroll position and therefore able to display a nice parallax effect.
4 |
5 | 
6 |
7 | ## Props
8 |
9 | Prop | Description | Type | Default
10 | ------ | ------ | ------ | ------
11 | containerStyle | Optional style for image's container | View Style Object | `{}`
12 | dimensions | Optional on-screen dimensions of the image, as measured with [native methods](https://facebook.github.io/react-native/docs/direct-manipulation.html#other-native-methods). This allows for a bit of optimization, but it's sometimes tricky to get these in responsive layouts. | `{ width: number, height: number }` | `undefined`
13 | fadeDuration | Duration of the fade-in effect when image is loaded | Number | `500`
14 | parallaxFactor | Speed of the parallax effect. Be aware that the bigger the value, the more image will appear "zoomed in". | Number | `0.3`
15 | showSpinner | Whether to display a spinner while image is loading or not | Boolean | `true`
16 | spinnerColor | Color of the spinner | String | 'rgba(0, 0, 0, 0.4)'
17 |
18 | All [`` props](https://facebook.github.io/react-native/docs/image.html#props) are also inherited, **particularly `source` which is required**.
19 |
20 | ## Usage
21 |
22 | The first thing you need to do is to **set `hasParallaxImages` to `true` on your ``**. This has two consequences:
23 | - migrating scroll events to the native driver for top-notch performances
24 | - your custom `renderItem` function now has access to a second argument that must be passed to the ``.
25 |
26 | Here is an example that shows how to connect images to your carousel (note the `parallaxProps` argument).
27 |
28 | ```javascript
29 | import Carousel, { ParallaxImage } from 'react-native-snap-carousel';
30 |
31 | export default class MyCarousel extends Component {
32 |
33 | _renderItem ({item, index}, parallaxProps) {
34 | return (
35 |
36 |
43 |
44 | { item.title }
45 |
46 |
47 | );
48 | }
49 |
50 | render () {
51 | return (
52 |
57 | );
58 | }
59 | ```
60 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | acorn-jsx@^3.0.0:
6 | version "3.0.1"
7 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
8 | dependencies:
9 | acorn "^3.0.4"
10 |
11 | acorn@^3.0.4:
12 | version "3.3.0"
13 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
14 |
15 | acorn@^5.0.1:
16 | version "5.0.3"
17 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
18 |
19 | ajv-keywords@^1.0.0:
20 | version "1.1.1"
21 | resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.1.1.tgz#02550bc605a3e576041565628af972e06c549d50"
22 |
23 | ajv@^4.7.0:
24 | version "4.9.0"
25 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.0.tgz#5a358085747b134eb567d6d15e015f1d7802f45c"
26 | dependencies:
27 | co "^4.6.0"
28 | json-stable-stringify "^1.0.1"
29 |
30 | ansi-escapes@^1.1.0:
31 | version "1.4.0"
32 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
33 |
34 | ansi-regex@^2.0.0:
35 | version "2.0.0"
36 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107"
37 |
38 | ansi-styles@^2.2.1:
39 | version "2.2.1"
40 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
41 |
42 | argparse@^1.0.7:
43 | version "1.0.9"
44 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
45 | dependencies:
46 | sprintf-js "~1.0.2"
47 |
48 | array-union@^1.0.1:
49 | version "1.0.2"
50 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
51 | dependencies:
52 | array-uniq "^1.0.1"
53 |
54 | array-uniq@^1.0.1:
55 | version "1.0.3"
56 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
57 |
58 | arrify@^1.0.0:
59 | version "1.0.1"
60 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
61 |
62 | asap@~2.0.3:
63 | version "2.0.5"
64 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
65 |
66 | babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
67 | version "6.22.0"
68 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
69 | dependencies:
70 | chalk "^1.1.0"
71 | esutils "^2.0.2"
72 | js-tokens "^3.0.0"
73 |
74 | babel-eslint@^7.2.3:
75 | version "7.2.3"
76 | resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827"
77 | dependencies:
78 | babel-code-frame "^6.22.0"
79 | babel-traverse "^6.23.1"
80 | babel-types "^6.23.0"
81 | babylon "^6.17.0"
82 |
83 | babel-messages@^6.23.0:
84 | version "6.23.0"
85 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
86 | dependencies:
87 | babel-runtime "^6.22.0"
88 |
89 | babel-runtime@^6.22.0:
90 | version "6.23.0"
91 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
92 | dependencies:
93 | core-js "^2.4.0"
94 | regenerator-runtime "^0.10.0"
95 |
96 | babel-traverse@^6.23.1:
97 | version "6.24.1"
98 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
99 | dependencies:
100 | babel-code-frame "^6.22.0"
101 | babel-messages "^6.23.0"
102 | babel-runtime "^6.22.0"
103 | babel-types "^6.24.1"
104 | babylon "^6.15.0"
105 | debug "^2.2.0"
106 | globals "^9.0.0"
107 | invariant "^2.2.0"
108 | lodash "^4.2.0"
109 |
110 | babel-types@^6.23.0, babel-types@^6.24.1:
111 | version "6.24.1"
112 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
113 | dependencies:
114 | babel-runtime "^6.22.0"
115 | esutils "^2.0.2"
116 | lodash "^4.2.0"
117 | to-fast-properties "^1.0.1"
118 |
119 | babylon@^6.15.0, babylon@^6.17.0:
120 | version "6.17.2"
121 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.2.tgz#201d25ef5f892c41bae49488b08db0dd476e9f5c"
122 |
123 | balanced-match@^0.4.1:
124 | version "0.4.2"
125 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
126 |
127 | brace-expansion@^1.0.0:
128 | version "1.1.6"
129 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
130 | dependencies:
131 | balanced-match "^0.4.1"
132 | concat-map "0.0.1"
133 |
134 | brace-expansion@^1.1.7:
135 | version "1.1.7"
136 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
137 | dependencies:
138 | balanced-match "^0.4.1"
139 | concat-map "0.0.1"
140 |
141 | builtin-modules@^1.0.0, builtin-modules@^1.1.1:
142 | version "1.1.1"
143 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
144 |
145 | caller-path@^0.1.0:
146 | version "0.1.0"
147 | resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
148 | dependencies:
149 | callsites "^0.2.0"
150 |
151 | callsites@^0.2.0:
152 | version "0.2.0"
153 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
154 |
155 | chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
156 | version "1.1.3"
157 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
158 | dependencies:
159 | ansi-styles "^2.2.1"
160 | escape-string-regexp "^1.0.2"
161 | has-ansi "^2.0.0"
162 | strip-ansi "^3.0.0"
163 | supports-color "^2.0.0"
164 |
165 | circular-json@^0.3.0:
166 | version "0.3.1"
167 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
168 |
169 | cli-cursor@^1.0.1:
170 | version "1.0.2"
171 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
172 | dependencies:
173 | restore-cursor "^1.0.1"
174 |
175 | cli-width@^2.0.0:
176 | version "2.1.0"
177 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
178 |
179 | co@^4.6.0:
180 | version "4.6.0"
181 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
182 |
183 | code-point-at@^1.0.0:
184 | version "1.1.0"
185 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
186 |
187 | concat-map@0.0.1:
188 | version "0.0.1"
189 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
190 |
191 | concat-stream@^1.5.2:
192 | version "1.6.0"
193 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
194 | dependencies:
195 | inherits "^2.0.3"
196 | readable-stream "^2.2.2"
197 | typedarray "^0.0.6"
198 |
199 | contains-path@^0.1.0:
200 | version "0.1.0"
201 | resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
202 |
203 | core-js@^1.0.0:
204 | version "1.2.7"
205 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
206 |
207 | core-js@^2.4.0:
208 | version "2.4.1"
209 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
210 |
211 | core-util-is@~1.0.0:
212 | version "1.0.2"
213 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
214 |
215 | d@^0.1.1, d@~0.1.1:
216 | version "0.1.1"
217 | resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309"
218 | dependencies:
219 | es5-ext "~0.10.2"
220 |
221 | debug@2.2.0:
222 | version "2.2.0"
223 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
224 | dependencies:
225 | ms "0.7.1"
226 |
227 | debug@^2.1.1, debug@^2.2.0:
228 | version "2.3.3"
229 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c"
230 | dependencies:
231 | ms "0.7.2"
232 |
233 | deep-is@~0.1.3:
234 | version "0.1.3"
235 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
236 |
237 | del@^2.0.2:
238 | version "2.2.2"
239 | resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
240 | dependencies:
241 | globby "^5.0.0"
242 | is-path-cwd "^1.0.0"
243 | is-path-in-cwd "^1.0.0"
244 | object-assign "^4.0.1"
245 | pify "^2.0.0"
246 | pinkie-promise "^2.0.0"
247 | rimraf "^2.2.8"
248 |
249 | doctrine@1.5.0:
250 | version "1.5.0"
251 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
252 | dependencies:
253 | esutils "^2.0.2"
254 | isarray "^1.0.0"
255 |
256 | doctrine@^2.0.0:
257 | version "2.0.0"
258 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
259 | dependencies:
260 | esutils "^2.0.2"
261 | isarray "^1.0.0"
262 |
263 | encoding@^0.1.11:
264 | version "0.1.12"
265 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
266 | dependencies:
267 | iconv-lite "~0.4.13"
268 |
269 | error-ex@^1.2.0:
270 | version "1.3.1"
271 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
272 | dependencies:
273 | is-arrayish "^0.2.1"
274 |
275 | es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7:
276 | version "0.10.12"
277 | resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047"
278 | dependencies:
279 | es6-iterator "2"
280 | es6-symbol "~3.1"
281 |
282 | es6-iterator@2:
283 | version "2.0.0"
284 | resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac"
285 | dependencies:
286 | d "^0.1.1"
287 | es5-ext "^0.10.7"
288 | es6-symbol "3"
289 |
290 | es6-map@^0.1.3:
291 | version "0.1.4"
292 | resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.4.tgz#a34b147be224773a4d7da8072794cefa3632b897"
293 | dependencies:
294 | d "~0.1.1"
295 | es5-ext "~0.10.11"
296 | es6-iterator "2"
297 | es6-set "~0.1.3"
298 | es6-symbol "~3.1.0"
299 | event-emitter "~0.3.4"
300 |
301 | es6-set@~0.1.3:
302 | version "0.1.4"
303 | resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.4.tgz#9516b6761c2964b92ff479456233a247dc707ce8"
304 | dependencies:
305 | d "~0.1.1"
306 | es5-ext "~0.10.11"
307 | es6-iterator "2"
308 | es6-symbol "3"
309 | event-emitter "~0.3.4"
310 |
311 | es6-symbol@3, es6-symbol@~3.1, es6-symbol@~3.1.0:
312 | version "3.1.0"
313 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa"
314 | dependencies:
315 | d "~0.1.1"
316 | es5-ext "~0.10.11"
317 |
318 | es6-weak-map@^2.0.1:
319 | version "2.0.1"
320 | resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81"
321 | dependencies:
322 | d "^0.1.1"
323 | es5-ext "^0.10.8"
324 | es6-iterator "2"
325 | es6-symbol "3"
326 |
327 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
328 | version "1.0.5"
329 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
330 |
331 | escope@^3.6.0:
332 | version "3.6.0"
333 | resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
334 | dependencies:
335 | es6-map "^0.1.3"
336 | es6-weak-map "^2.0.1"
337 | esrecurse "^4.1.0"
338 | estraverse "^4.1.1"
339 |
340 | eslint-config-standard-jsx@^4.0.0:
341 | version "4.0.1"
342 | resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.1.tgz#cd4e463d0268e2d9e707f61f42f73f5b3333c642"
343 |
344 | eslint-config-standard-react@^5.0.0:
345 | version "5.0.0"
346 | resolved "https://registry.yarnpkg.com/eslint-config-standard-react/-/eslint-config-standard-react-5.0.0.tgz#64c7b8140172852be810a53d48ee87649ff178e3"
347 | dependencies:
348 | eslint-config-standard-jsx "^4.0.0"
349 |
350 | eslint-config-standard@^10.2.1:
351 | version "10.2.1"
352 | resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591"
353 |
354 | eslint-import-resolver-node@^0.2.0:
355 | version "0.2.3"
356 | resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c"
357 | dependencies:
358 | debug "^2.2.0"
359 | object-assign "^4.0.1"
360 | resolve "^1.1.6"
361 |
362 | eslint-module-utils@^2.0.0:
363 | version "2.0.0"
364 | resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz#a6f8c21d901358759cdc35dbac1982ae1ee58bce"
365 | dependencies:
366 | debug "2.2.0"
367 | pkg-dir "^1.0.0"
368 |
369 | eslint-plugin-import@^2.3.0:
370 | version "2.3.0"
371 | resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz#37c801e0ada0e296cbdf20c3f393acb5b52af36b"
372 | dependencies:
373 | builtin-modules "^1.1.1"
374 | contains-path "^0.1.0"
375 | debug "^2.2.0"
376 | doctrine "1.5.0"
377 | eslint-import-resolver-node "^0.2.0"
378 | eslint-module-utils "^2.0.0"
379 | has "^1.0.1"
380 | lodash.cond "^4.3.0"
381 | minimatch "^3.0.3"
382 | read-pkg-up "^2.0.0"
383 |
384 | eslint-plugin-node@^5.0.0:
385 | version "5.0.0"
386 | resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.0.0.tgz#948b1fb82e3f0a744e86fad19aa4f49537d246cc"
387 | dependencies:
388 | ignore "^3.3.3"
389 | minimatch "^3.0.4"
390 | resolve "^1.3.3"
391 | semver "5.3.0"
392 |
393 | eslint-plugin-promise@^3.5.0:
394 | version "3.5.0"
395 | resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
396 |
397 | eslint-plugin-react@^7.0.1:
398 | version "7.0.1"
399 | resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.0.1.tgz#e78107e1e559c6e2b17786bb67c2e2a010ad0d2f"
400 | dependencies:
401 | doctrine "^2.0.0"
402 | has "^1.0.1"
403 | jsx-ast-utils "^1.3.4"
404 |
405 | eslint-plugin-standard@^3.0.1:
406 | version "3.0.1"
407 | resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2"
408 |
409 | eslint@^3.19.0:
410 | version "3.19.0"
411 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
412 | dependencies:
413 | babel-code-frame "^6.16.0"
414 | chalk "^1.1.3"
415 | concat-stream "^1.5.2"
416 | debug "^2.1.1"
417 | doctrine "^2.0.0"
418 | escope "^3.6.0"
419 | espree "^3.4.0"
420 | esquery "^1.0.0"
421 | estraverse "^4.2.0"
422 | esutils "^2.0.2"
423 | file-entry-cache "^2.0.0"
424 | glob "^7.0.3"
425 | globals "^9.14.0"
426 | ignore "^3.2.0"
427 | imurmurhash "^0.1.4"
428 | inquirer "^0.12.0"
429 | is-my-json-valid "^2.10.0"
430 | is-resolvable "^1.0.0"
431 | js-yaml "^3.5.1"
432 | json-stable-stringify "^1.0.0"
433 | levn "^0.3.0"
434 | lodash "^4.0.0"
435 | mkdirp "^0.5.0"
436 | natural-compare "^1.4.0"
437 | optionator "^0.8.2"
438 | path-is-inside "^1.0.1"
439 | pluralize "^1.2.1"
440 | progress "^1.1.8"
441 | require-uncached "^1.0.2"
442 | shelljs "^0.7.5"
443 | strip-bom "^3.0.0"
444 | strip-json-comments "~2.0.1"
445 | table "^3.7.8"
446 | text-table "~0.2.0"
447 | user-home "^2.0.0"
448 |
449 | espree@^3.4.0:
450 | version "3.4.3"
451 | resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374"
452 | dependencies:
453 | acorn "^5.0.1"
454 | acorn-jsx "^3.0.0"
455 |
456 | esprima@^2.6.0:
457 | version "2.7.3"
458 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
459 |
460 | esquery@^1.0.0:
461 | version "1.0.0"
462 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
463 | dependencies:
464 | estraverse "^4.0.0"
465 |
466 | esrecurse@^4.1.0:
467 | version "4.1.0"
468 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220"
469 | dependencies:
470 | estraverse "~4.1.0"
471 | object-assign "^4.0.1"
472 |
473 | estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0:
474 | version "4.2.0"
475 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
476 |
477 | estraverse@~4.1.0:
478 | version "4.1.1"
479 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2"
480 |
481 | esutils@^2.0.2:
482 | version "2.0.2"
483 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
484 |
485 | event-emitter@~0.3.4:
486 | version "0.3.4"
487 | resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.4.tgz#8d63ddfb4cfe1fae3b32ca265c4c720222080bb5"
488 | dependencies:
489 | d "~0.1.1"
490 | es5-ext "~0.10.7"
491 |
492 | exit-hook@^1.0.0:
493 | version "1.1.1"
494 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
495 |
496 | fast-levenshtein@~2.0.4:
497 | version "2.0.5"
498 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.5.tgz#bd33145744519ab1c36c3ee9f31f08e9079b67f2"
499 |
500 | fbjs@^0.8.4:
501 | version "0.8.12"
502 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
503 | dependencies:
504 | core-js "^1.0.0"
505 | isomorphic-fetch "^2.1.1"
506 | loose-envify "^1.0.0"
507 | object-assign "^4.1.0"
508 | promise "^7.1.1"
509 | setimmediate "^1.0.5"
510 | ua-parser-js "^0.7.9"
511 |
512 | figures@^1.3.5:
513 | version "1.7.0"
514 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
515 | dependencies:
516 | escape-string-regexp "^1.0.5"
517 | object-assign "^4.1.0"
518 |
519 | file-entry-cache@^2.0.0:
520 | version "2.0.0"
521 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
522 | dependencies:
523 | flat-cache "^1.2.1"
524 | object-assign "^4.0.1"
525 |
526 | find-up@^1.0.0:
527 | version "1.1.2"
528 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
529 | dependencies:
530 | path-exists "^2.0.0"
531 | pinkie-promise "^2.0.0"
532 |
533 | find-up@^2.0.0:
534 | version "2.1.0"
535 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
536 | dependencies:
537 | locate-path "^2.0.0"
538 |
539 | flat-cache@^1.2.1:
540 | version "1.2.1"
541 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.1.tgz#6c837d6225a7de5659323740b36d5361f71691ff"
542 | dependencies:
543 | circular-json "^0.3.0"
544 | del "^2.0.2"
545 | graceful-fs "^4.1.2"
546 | write "^0.2.1"
547 |
548 | fs.realpath@^1.0.0:
549 | version "1.0.0"
550 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
551 |
552 | function-bind@^1.0.2:
553 | version "1.1.0"
554 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
555 |
556 | generate-function@^2.0.0:
557 | version "2.0.0"
558 | resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
559 |
560 | generate-object-property@^1.1.0:
561 | version "1.2.0"
562 | resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
563 | dependencies:
564 | is-property "^1.0.0"
565 |
566 | glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
567 | version "7.1.1"
568 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
569 | dependencies:
570 | fs.realpath "^1.0.0"
571 | inflight "^1.0.4"
572 | inherits "2"
573 | minimatch "^3.0.2"
574 | once "^1.3.0"
575 | path-is-absolute "^1.0.0"
576 |
577 | globals@^9.0.0, globals@^9.14.0:
578 | version "9.14.0"
579 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034"
580 |
581 | globby@^5.0.0:
582 | version "5.0.0"
583 | resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
584 | dependencies:
585 | array-union "^1.0.1"
586 | arrify "^1.0.0"
587 | glob "^7.0.3"
588 | object-assign "^4.0.1"
589 | pify "^2.0.0"
590 | pinkie-promise "^2.0.0"
591 |
592 | graceful-fs@^4.1.2:
593 | version "4.1.11"
594 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
595 |
596 | has-ansi@^2.0.0:
597 | version "2.0.0"
598 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
599 | dependencies:
600 | ansi-regex "^2.0.0"
601 |
602 | has@^1.0.1:
603 | version "1.0.1"
604 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
605 | dependencies:
606 | function-bind "^1.0.2"
607 |
608 | hosted-git-info@^2.1.4:
609 | version "2.4.2"
610 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
611 |
612 | iconv-lite@~0.4.13:
613 | version "0.4.17"
614 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d"
615 |
616 | ignore@^3.2.0:
617 | version "3.2.0"
618 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.0.tgz#8d88f03c3002a0ac52114db25d2c673b0bf1e435"
619 |
620 | ignore@^3.3.3:
621 | version "3.3.3"
622 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
623 |
624 | imurmurhash@^0.1.4:
625 | version "0.1.4"
626 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
627 |
628 | inflight@^1.0.4:
629 | version "1.0.6"
630 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
631 | dependencies:
632 | once "^1.3.0"
633 | wrappy "1"
634 |
635 | inherits@2, inherits@^2.0.3, inherits@~2.0.1:
636 | version "2.0.3"
637 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
638 |
639 | inquirer@^0.12.0:
640 | version "0.12.0"
641 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
642 | dependencies:
643 | ansi-escapes "^1.1.0"
644 | ansi-regex "^2.0.0"
645 | chalk "^1.0.0"
646 | cli-cursor "^1.0.1"
647 | cli-width "^2.0.0"
648 | figures "^1.3.5"
649 | lodash "^4.3.0"
650 | readline2 "^1.0.1"
651 | run-async "^0.1.0"
652 | rx-lite "^3.1.2"
653 | string-width "^1.0.1"
654 | strip-ansi "^3.0.0"
655 | through "^2.3.6"
656 |
657 | interpret@^1.0.0:
658 | version "1.0.1"
659 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
660 |
661 | invariant@^2.2.0:
662 | version "2.2.2"
663 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
664 | dependencies:
665 | loose-envify "^1.0.0"
666 |
667 | is-arrayish@^0.2.1:
668 | version "0.2.1"
669 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
670 |
671 | is-builtin-module@^1.0.0:
672 | version "1.0.0"
673 | resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
674 | dependencies:
675 | builtin-modules "^1.0.0"
676 |
677 | is-fullwidth-code-point@^1.0.0:
678 | version "1.0.0"
679 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
680 | dependencies:
681 | number-is-nan "^1.0.0"
682 |
683 | is-fullwidth-code-point@^2.0.0:
684 | version "2.0.0"
685 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
686 |
687 | is-my-json-valid@^2.10.0:
688 | version "2.15.0"
689 | resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"
690 | dependencies:
691 | generate-function "^2.0.0"
692 | generate-object-property "^1.1.0"
693 | jsonpointer "^4.0.0"
694 | xtend "^4.0.0"
695 |
696 | is-path-cwd@^1.0.0:
697 | version "1.0.0"
698 | resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
699 |
700 | is-path-in-cwd@^1.0.0:
701 | version "1.0.0"
702 | resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
703 | dependencies:
704 | is-path-inside "^1.0.0"
705 |
706 | is-path-inside@^1.0.0:
707 | version "1.0.0"
708 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f"
709 | dependencies:
710 | path-is-inside "^1.0.1"
711 |
712 | is-property@^1.0.0:
713 | version "1.0.2"
714 | resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
715 |
716 | is-resolvable@^1.0.0:
717 | version "1.0.0"
718 | resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
719 | dependencies:
720 | tryit "^1.0.1"
721 |
722 | is-stream@^1.0.1:
723 | version "1.1.0"
724 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
725 |
726 | isarray@^1.0.0, isarray@~1.0.0:
727 | version "1.0.0"
728 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
729 |
730 | isomorphic-fetch@^2.1.1:
731 | version "2.2.1"
732 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
733 | dependencies:
734 | node-fetch "^1.0.1"
735 | whatwg-fetch ">=0.10.0"
736 |
737 | js-tokens@^2.0.0:
738 | version "2.0.0"
739 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5"
740 |
741 | js-tokens@^3.0.0:
742 | version "3.0.1"
743 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
744 |
745 | js-yaml@^3.5.1:
746 | version "3.7.0"
747 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
748 | dependencies:
749 | argparse "^1.0.7"
750 | esprima "^2.6.0"
751 |
752 | json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
753 | version "1.0.1"
754 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
755 | dependencies:
756 | jsonify "~0.0.0"
757 |
758 | jsonify@~0.0.0:
759 | version "0.0.0"
760 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
761 |
762 | jsonpointer@^4.0.0:
763 | version "4.0.0"
764 | resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5"
765 |
766 | jsx-ast-utils@^1.3.4:
767 | version "1.4.1"
768 | resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
769 |
770 | levn@^0.3.0, levn@~0.3.0:
771 | version "0.3.0"
772 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
773 | dependencies:
774 | prelude-ls "~1.1.2"
775 | type-check "~0.3.2"
776 |
777 | load-json-file@^2.0.0:
778 | version "2.0.0"
779 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
780 | dependencies:
781 | graceful-fs "^4.1.2"
782 | parse-json "^2.2.0"
783 | pify "^2.0.0"
784 | strip-bom "^3.0.0"
785 |
786 | locate-path@^2.0.0:
787 | version "2.0.0"
788 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
789 | dependencies:
790 | p-locate "^2.0.0"
791 | path-exists "^3.0.0"
792 |
793 | lodash.cond@^4.3.0:
794 | version "4.5.2"
795 | resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5"
796 |
797 | lodash.debounce@4.0.8:
798 | version "4.0.8"
799 | resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
800 |
801 | lodash.throttle@4.1.1:
802 | version "4.1.1"
803 | resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
804 |
805 | lodash@^4.0.0, lodash@^4.2.0, lodash@^4.3.0:
806 | version "4.17.2"
807 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42"
808 |
809 | loose-envify@^1.0.0:
810 | version "1.3.0"
811 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.0.tgz#6b26248c42f6d4fa4b0d8542f78edfcde35642a8"
812 | dependencies:
813 | js-tokens "^2.0.0"
814 |
815 | minimatch@^3.0.2, minimatch@^3.0.3:
816 | version "3.0.3"
817 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
818 | dependencies:
819 | brace-expansion "^1.0.0"
820 |
821 | minimatch@^3.0.4:
822 | version "3.0.4"
823 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
824 | dependencies:
825 | brace-expansion "^1.1.7"
826 |
827 | minimist@0.0.8:
828 | version "0.0.8"
829 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
830 |
831 | mkdirp@^0.5.0, mkdirp@^0.5.1:
832 | version "0.5.1"
833 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
834 | dependencies:
835 | minimist "0.0.8"
836 |
837 | ms@0.7.1:
838 | version "0.7.1"
839 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
840 |
841 | ms@0.7.2:
842 | version "0.7.2"
843 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
844 |
845 | mute-stream@0.0.5:
846 | version "0.0.5"
847 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
848 |
849 | natural-compare@^1.4.0:
850 | version "1.4.0"
851 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
852 |
853 | node-fetch@^1.0.1:
854 | version "1.7.1"
855 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.1.tgz#899cb3d0a3c92f952c47f1b876f4c8aeabd400d5"
856 | dependencies:
857 | encoding "^0.1.11"
858 | is-stream "^1.0.1"
859 |
860 | normalize-package-data@^2.3.2:
861 | version "2.3.8"
862 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
863 | dependencies:
864 | hosted-git-info "^2.1.4"
865 | is-builtin-module "^1.0.0"
866 | semver "2 || 3 || 4 || 5"
867 | validate-npm-package-license "^3.0.1"
868 |
869 | number-is-nan@^1.0.0:
870 | version "1.0.1"
871 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
872 |
873 | object-assign@^4.0.1, object-assign@^4.1.0:
874 | version "4.1.0"
875 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
876 |
877 | once@^1.3.0:
878 | version "1.4.0"
879 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
880 | dependencies:
881 | wrappy "1"
882 |
883 | onetime@^1.0.0:
884 | version "1.1.0"
885 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
886 |
887 | optionator@^0.8.2:
888 | version "0.8.2"
889 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
890 | dependencies:
891 | deep-is "~0.1.3"
892 | fast-levenshtein "~2.0.4"
893 | levn "~0.3.0"
894 | prelude-ls "~1.1.2"
895 | type-check "~0.3.2"
896 | wordwrap "~1.0.0"
897 |
898 | os-homedir@^1.0.0:
899 | version "1.0.2"
900 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
901 |
902 | p-limit@^1.1.0:
903 | version "1.1.0"
904 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
905 |
906 | p-locate@^2.0.0:
907 | version "2.0.0"
908 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
909 | dependencies:
910 | p-limit "^1.1.0"
911 |
912 | parse-json@^2.2.0:
913 | version "2.2.0"
914 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
915 | dependencies:
916 | error-ex "^1.2.0"
917 |
918 | path-exists@^2.0.0:
919 | version "2.1.0"
920 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
921 | dependencies:
922 | pinkie-promise "^2.0.0"
923 |
924 | path-exists@^3.0.0:
925 | version "3.0.0"
926 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
927 |
928 | path-is-absolute@^1.0.0:
929 | version "1.0.1"
930 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
931 |
932 | path-is-inside@^1.0.1:
933 | version "1.0.2"
934 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
935 |
936 | path-parse@^1.0.5:
937 | version "1.0.5"
938 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
939 |
940 | path-type@^2.0.0:
941 | version "2.0.0"
942 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
943 | dependencies:
944 | pify "^2.0.0"
945 |
946 | pify@^2.0.0:
947 | version "2.3.0"
948 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
949 |
950 | pinkie-promise@^2.0.0:
951 | version "2.0.1"
952 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
953 | dependencies:
954 | pinkie "^2.0.0"
955 |
956 | pinkie@^2.0.0:
957 | version "2.0.4"
958 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
959 |
960 | pkg-dir@^1.0.0:
961 | version "1.0.0"
962 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
963 | dependencies:
964 | find-up "^1.0.0"
965 |
966 | pluralize@^1.2.1:
967 | version "1.2.1"
968 | resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
969 |
970 | prelude-ls@~1.1.2:
971 | version "1.1.2"
972 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
973 |
974 | process-nextick-args@~1.0.6:
975 | version "1.0.7"
976 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
977 |
978 | progress@^1.1.8:
979 | version "1.1.8"
980 | resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
981 |
982 | promise@^7.1.1:
983 | version "7.1.1"
984 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
985 | dependencies:
986 | asap "~2.0.3"
987 |
988 | react-addons-shallow-compare@15.5.2:
989 | version "15.5.2"
990 | resolved "https://registry.yarnpkg.com/react-addons-shallow-compare/-/react-addons-shallow-compare-15.5.2.tgz#7cb0ee7acc8d7c93fcc202df0bf47ba916a7bdad"
991 | dependencies:
992 | fbjs "^0.8.4"
993 | object-assign "^4.1.0"
994 |
995 | read-pkg-up@^2.0.0:
996 | version "2.0.0"
997 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
998 | dependencies:
999 | find-up "^2.0.0"
1000 | read-pkg "^2.0.0"
1001 |
1002 | read-pkg@^2.0.0:
1003 | version "2.0.0"
1004 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
1005 | dependencies:
1006 | load-json-file "^2.0.0"
1007 | normalize-package-data "^2.3.2"
1008 | path-type "^2.0.0"
1009 |
1010 | readable-stream@^2.2.2:
1011 | version "2.2.11"
1012 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.11.tgz#0796b31f8d7688007ff0b93a8088d34aa17c0f72"
1013 | dependencies:
1014 | core-util-is "~1.0.0"
1015 | inherits "~2.0.1"
1016 | isarray "~1.0.0"
1017 | process-nextick-args "~1.0.6"
1018 | safe-buffer "~5.0.1"
1019 | string_decoder "~1.0.0"
1020 | util-deprecate "~1.0.1"
1021 |
1022 | readline2@^1.0.1:
1023 | version "1.0.1"
1024 | resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
1025 | dependencies:
1026 | code-point-at "^1.0.0"
1027 | is-fullwidth-code-point "^1.0.0"
1028 | mute-stream "0.0.5"
1029 |
1030 | rechoir@^0.6.2:
1031 | version "0.6.2"
1032 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
1033 | dependencies:
1034 | resolve "^1.1.6"
1035 |
1036 | regenerator-runtime@^0.10.0:
1037 | version "0.10.5"
1038 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
1039 |
1040 | require-uncached@^1.0.2:
1041 | version "1.0.3"
1042 | resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
1043 | dependencies:
1044 | caller-path "^0.1.0"
1045 | resolve-from "^1.0.0"
1046 |
1047 | resolve-from@^1.0.0:
1048 | version "1.0.1"
1049 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
1050 |
1051 | resolve@^1.1.6:
1052 | version "1.1.7"
1053 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
1054 |
1055 | resolve@^1.3.3:
1056 | version "1.3.3"
1057 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
1058 | dependencies:
1059 | path-parse "^1.0.5"
1060 |
1061 | restore-cursor@^1.0.1:
1062 | version "1.0.1"
1063 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
1064 | dependencies:
1065 | exit-hook "^1.0.0"
1066 | onetime "^1.0.0"
1067 |
1068 | rimraf@^2.2.8:
1069 | version "2.5.4"
1070 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
1071 | dependencies:
1072 | glob "^7.0.5"
1073 |
1074 | run-async@^0.1.0:
1075 | version "0.1.0"
1076 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
1077 | dependencies:
1078 | once "^1.3.0"
1079 |
1080 | rx-lite@^3.1.2:
1081 | version "3.1.2"
1082 | resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
1083 |
1084 | safe-buffer@~5.0.1:
1085 | version "5.0.1"
1086 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
1087 |
1088 | "semver@2 || 3 || 4 || 5", semver@5.3.0:
1089 | version "5.3.0"
1090 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
1091 |
1092 | setimmediate@^1.0.5:
1093 | version "1.0.5"
1094 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
1095 |
1096 | shelljs@^0.7.5:
1097 | version "0.7.5"
1098 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675"
1099 | dependencies:
1100 | glob "^7.0.0"
1101 | interpret "^1.0.0"
1102 | rechoir "^0.6.2"
1103 |
1104 | slice-ansi@0.0.4:
1105 | version "0.0.4"
1106 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
1107 |
1108 | spdx-correct@~1.0.0:
1109 | version "1.0.2"
1110 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
1111 | dependencies:
1112 | spdx-license-ids "^1.0.2"
1113 |
1114 | spdx-expression-parse@~1.0.0:
1115 | version "1.0.4"
1116 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
1117 |
1118 | spdx-license-ids@^1.0.2:
1119 | version "1.2.2"
1120 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
1121 |
1122 | sprintf-js@~1.0.2:
1123 | version "1.0.3"
1124 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
1125 |
1126 | string-width@^1.0.1:
1127 | version "1.0.2"
1128 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
1129 | dependencies:
1130 | code-point-at "^1.0.0"
1131 | is-fullwidth-code-point "^1.0.0"
1132 | strip-ansi "^3.0.0"
1133 |
1134 | string-width@^2.0.0:
1135 | version "2.0.0"
1136 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e"
1137 | dependencies:
1138 | is-fullwidth-code-point "^2.0.0"
1139 | strip-ansi "^3.0.0"
1140 |
1141 | string_decoder@~1.0.0:
1142 | version "1.0.2"
1143 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.2.tgz#b29e1f4e1125fa97a10382b8a533737b7491e179"
1144 | dependencies:
1145 | safe-buffer "~5.0.1"
1146 |
1147 | strip-ansi@^3.0.0:
1148 | version "3.0.1"
1149 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
1150 | dependencies:
1151 | ansi-regex "^2.0.0"
1152 |
1153 | strip-bom@^3.0.0:
1154 | version "3.0.0"
1155 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
1156 |
1157 | strip-json-comments@~2.0.1:
1158 | version "2.0.1"
1159 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
1160 |
1161 | supports-color@^2.0.0:
1162 | version "2.0.0"
1163 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
1164 |
1165 | table@^3.7.8:
1166 | version "3.8.3"
1167 | resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
1168 | dependencies:
1169 | ajv "^4.7.0"
1170 | ajv-keywords "^1.0.0"
1171 | chalk "^1.1.1"
1172 | lodash "^4.0.0"
1173 | slice-ansi "0.0.4"
1174 | string-width "^2.0.0"
1175 |
1176 | text-table@~0.2.0:
1177 | version "0.2.0"
1178 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
1179 |
1180 | through@^2.3.6:
1181 | version "2.3.8"
1182 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
1183 |
1184 | to-fast-properties@^1.0.1:
1185 | version "1.0.2"
1186 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320"
1187 |
1188 | tryit@^1.0.1:
1189 | version "1.0.3"
1190 | resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
1191 |
1192 | type-check@~0.3.2:
1193 | version "0.3.2"
1194 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
1195 | dependencies:
1196 | prelude-ls "~1.1.2"
1197 |
1198 | typedarray@^0.0.6:
1199 | version "0.0.6"
1200 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
1201 |
1202 | ua-parser-js@^0.7.9:
1203 | version "0.7.12"
1204 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
1205 |
1206 | user-home@^2.0.0:
1207 | version "2.0.0"
1208 | resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
1209 | dependencies:
1210 | os-homedir "^1.0.0"
1211 |
1212 | util-deprecate@~1.0.1:
1213 | version "1.0.2"
1214 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
1215 |
1216 | validate-npm-package-license@^3.0.1:
1217 | version "3.0.1"
1218 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
1219 | dependencies:
1220 | spdx-correct "~1.0.0"
1221 | spdx-expression-parse "~1.0.0"
1222 |
1223 | whatwg-fetch@>=0.10.0:
1224 | version "2.0.3"
1225 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
1226 |
1227 | wordwrap@~1.0.0:
1228 | version "1.0.0"
1229 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
1230 |
1231 | wrappy@1:
1232 | version "1.0.2"
1233 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
1234 |
1235 | write@^0.2.1:
1236 | version "0.2.1"
1237 | resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
1238 | dependencies:
1239 | mkdirp "^0.5.1"
1240 |
1241 | xtend@^4.0.0:
1242 | version "4.0.1"
1243 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
1244 |
--------------------------------------------------------------------------------