@momo-kits/carousel 0.73.3-beta.5 → 0.74.2-react-native.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/animation.ts +62 -0
- package/index.tsx +830 -0
- package/package.json +13 -11
- package/publish.sh +1 -1
- package/styles.ts +0 -0
- package/types.ts +63 -0
- package/Carousel.js +0 -1369
- package/CarouselV2.js +0 -1363
- package/index.js +0 -5
- package/pagination/NumberPagination.js +0 -43
- package/pagination/Pagination.js +0 -188
- package/pagination/PaginationDot.js +0 -151
- package/pagination/styles.js +0 -24
- package/styles.js +0 -189
- package/utils/animation.js +0 -329
- package/utils/animationsV2.js +0 -381
package/Carousel.js
DELETED
|
@@ -1,1369 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-undef */
|
|
2
|
-
/* eslint-disable no-lonely-if */
|
|
3
|
-
/* eslint-disable no-param-reassign */
|
|
4
|
-
/* eslint-disable react/jsx-props-no-spreading */
|
|
5
|
-
import React, { PureComponent } from 'react';
|
|
6
|
-
import {
|
|
7
|
-
Animated, Easing, FlatList, I18nManager, Platform, ScrollView, View, ViewPropTypes
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
import PropTypes from 'prop-types';
|
|
10
|
-
import {
|
|
11
|
-
defaultScrollInterpolator,
|
|
12
|
-
stackScrollInterpolator,
|
|
13
|
-
tinderScrollInterpolator,
|
|
14
|
-
defaultAnimatedStyles,
|
|
15
|
-
shiftAnimatedStyles,
|
|
16
|
-
stackAnimatedStyles,
|
|
17
|
-
tinderAnimatedStyles
|
|
18
|
-
} from './utils/animation';
|
|
19
|
-
|
|
20
|
-
const IS_IOS = Platform.OS === 'ios';
|
|
21
|
-
const IS_RTL = I18nManager.isRTL;
|
|
22
|
-
|
|
23
|
-
export default class Carousel extends PureComponent {
|
|
24
|
-
constructor (props) {
|
|
25
|
-
super(props);
|
|
26
|
-
|
|
27
|
-
this.state = {
|
|
28
|
-
hideCarousel: true,
|
|
29
|
-
interpolators: []
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// The following values are not stored in the state because 'setState()' is asynchronous
|
|
33
|
-
// and this results in an absolutely crappy behavior on Android while swiping (see #156)
|
|
34
|
-
const initialActiveItem = this._getFirstItem(props.firstItem);
|
|
35
|
-
this._activeItem = initialActiveItem;
|
|
36
|
-
this._previousActiveItem = initialActiveItem;
|
|
37
|
-
this._previousFirstItem = initialActiveItem;
|
|
38
|
-
this._previousItemsLength = initialActiveItem;
|
|
39
|
-
|
|
40
|
-
this._mounted = false;
|
|
41
|
-
this._positions = [];
|
|
42
|
-
this._currentContentOffset = 0; // store ScrollView's scroll position
|
|
43
|
-
this._canFireBeforeCallback = false;
|
|
44
|
-
this._canFireCallback = false;
|
|
45
|
-
this._scrollOffsetRef = null;
|
|
46
|
-
this._onScrollTriggered = true; // used when momentum is enabled to prevent an issue with edges items
|
|
47
|
-
this._lastScrollDate = 0; // used to work around a FlatList bug
|
|
48
|
-
this._scrollEnabled = props.scrollEnabled !== false;
|
|
49
|
-
|
|
50
|
-
this._initPositionsAndInterpolators = this._initPositionsAndInterpolators.bind(this);
|
|
51
|
-
this._renderItem = this._renderItem.bind(this);
|
|
52
|
-
this._onSnap = this._onSnap.bind(this);
|
|
53
|
-
|
|
54
|
-
this._onLayout = this._onLayout.bind(this);
|
|
55
|
-
this._onScroll = this._onScroll.bind(this);
|
|
56
|
-
this._onScrollBeginDrag = props.enableSnap ? this._onScrollBeginDrag.bind(this) : undefined;
|
|
57
|
-
this._onScrollEnd = props.enableSnap || props.autoplay ? this._onScrollEnd.bind(this) : undefined;
|
|
58
|
-
this._onScrollEndDrag = !props.enableMomentum ? this._onScrollEndDrag.bind(this) : undefined;
|
|
59
|
-
this._onMomentumScrollEnd = props.enableMomentum ? this._onMomentumScrollEnd.bind(this) : undefined;
|
|
60
|
-
this._onTouchStart = this._onTouchStart.bind(this);
|
|
61
|
-
this._onTouchEnd = this._onTouchEnd.bind(this);
|
|
62
|
-
this._onTouchRelease = this._onTouchRelease.bind(this);
|
|
63
|
-
|
|
64
|
-
this._getKeyExtractor = this._getKeyExtractor.bind(this);
|
|
65
|
-
|
|
66
|
-
this._setScrollHandler(props);
|
|
67
|
-
|
|
68
|
-
// This bool aims at fixing an iOS bug due to scrollTo that triggers onMomentumScrollEnd.
|
|
69
|
-
// onMomentumScrollEnd fires this._snapScroll, thus creating an infinite loop.
|
|
70
|
-
this._ignoreNextMomentum = false;
|
|
71
|
-
|
|
72
|
-
// Warnings
|
|
73
|
-
if (!ViewPropTypes) {
|
|
74
|
-
console.warn('react-native-snap-carousel: It is recommended to use at least version 0.44 of React Native with the plugin');
|
|
75
|
-
}
|
|
76
|
-
if (!props.vertical && (!props.sliderWidth || !props.itemWidth)) {
|
|
77
|
-
console.error('react-native-snap-carousel: You need to specify both `sliderWidth` and `itemWidth` for horizontal carousels');
|
|
78
|
-
}
|
|
79
|
-
if (props.vertical && (!props.sliderHeight || !props.itemHeight)) {
|
|
80
|
-
console.error('react-native-snap-carousel: You need to specify both `sliderHeight` and `itemHeight` for vertical carousels');
|
|
81
|
-
}
|
|
82
|
-
if (props.apparitionDelay && !IS_IOS && !props.useScrollView) {
|
|
83
|
-
console.warn('react-native-snap-carousel: Using `apparitionDelay` on Android is not recommended since it can lead to rendering issues');
|
|
84
|
-
}
|
|
85
|
-
if (props.customAnimationType || props.customAnimationOptions) {
|
|
86
|
-
console.warn('react-native-snap-carousel: Props `customAnimationType` and `customAnimationOptions` have been renamed to `activeAnimationType` and `activeAnimationOptions`');
|
|
87
|
-
}
|
|
88
|
-
if (props.onScrollViewScroll) {
|
|
89
|
-
console.error('react-native-snap-carousel: Prop `onScrollViewScroll` has been removed. Use `onScroll` instead');
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
componentDidMount () {
|
|
94
|
-
const { apparitionDelay, autoplay, firstItem } = this.props;
|
|
95
|
-
const _firstItem = this._getFirstItem(firstItem);
|
|
96
|
-
const apparitionCallback = () => {
|
|
97
|
-
this.setState({ hideCarousel: false });
|
|
98
|
-
if (autoplay) {
|
|
99
|
-
this.startAutoplay();
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
this._mounted = true;
|
|
104
|
-
this._initPositionsAndInterpolators();
|
|
105
|
-
|
|
106
|
-
// Without 'requestAnimationFrame' or a `0` timeout, images will randomly not be rendered on Android...
|
|
107
|
-
requestAnimationFrame(() => {
|
|
108
|
-
if (!this._mounted) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
this._snapToItem(_firstItem, false, false, true, false);
|
|
113
|
-
this._hackActiveSlideAnimation(_firstItem, 'start', true);
|
|
114
|
-
|
|
115
|
-
if (apparitionDelay) {
|
|
116
|
-
this._apparitionTimeout = setTimeout(() => {
|
|
117
|
-
apparitionCallback();
|
|
118
|
-
}, apparitionDelay);
|
|
119
|
-
} else {
|
|
120
|
-
apparitionCallback();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// shouldComponentUpdate (nextProps, nextState) {
|
|
126
|
-
// if (this.props.shouldOptimizeUpdates === false) {
|
|
127
|
-
// return true;
|
|
128
|
-
// } else {
|
|
129
|
-
// return shallowCompare(this, nextProps, nextState);
|
|
130
|
-
// }
|
|
131
|
-
// }
|
|
132
|
-
|
|
133
|
-
componentDidUpdate (prevProps) {
|
|
134
|
-
const { interpolators } = this.state;
|
|
135
|
-
const { firstItem, itemHeight, itemWidth, scrollEnabled, sliderHeight, sliderWidth } = this.props;
|
|
136
|
-
const itemsLength = this._getCustomDataLength(this.props);
|
|
137
|
-
|
|
138
|
-
if (!itemsLength) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const nextFirstItem = this._getFirstItem(firstItem, this.props);
|
|
143
|
-
let nextActiveItem = this._activeItem || this._activeItem === 0 ? this._activeItem : nextFirstItem;
|
|
144
|
-
|
|
145
|
-
const hasNewSliderWidth = sliderWidth && sliderWidth !== prevProps.sliderWidth;
|
|
146
|
-
const hasNewSliderHeight = sliderHeight && sliderHeight !== prevProps.sliderHeight;
|
|
147
|
-
const hasNewItemWidth = itemWidth && itemWidth !== prevProps.itemWidth;
|
|
148
|
-
const hasNewItemHeight = itemHeight && itemHeight !== prevProps.itemHeight;
|
|
149
|
-
const hasNewScrollEnabled = scrollEnabled !== prevProps.scrollEnabled;
|
|
150
|
-
|
|
151
|
-
// Prevent issues with dynamically removed items
|
|
152
|
-
if (nextActiveItem > itemsLength - 1) {
|
|
153
|
-
nextActiveItem = itemsLength - 1;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Handle changing scrollEnabled independent of user -> carousel interaction
|
|
157
|
-
if (hasNewScrollEnabled) {
|
|
158
|
-
this._setScrollEnabled(scrollEnabled);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (interpolators.length !== itemsLength || hasNewSliderWidth ||
|
|
162
|
-
hasNewSliderHeight || hasNewItemWidth || hasNewItemHeight) {
|
|
163
|
-
this._activeItem = nextActiveItem;
|
|
164
|
-
this._previousItemsLength = itemsLength;
|
|
165
|
-
|
|
166
|
-
this._initPositionsAndInterpolators(this.props);
|
|
167
|
-
|
|
168
|
-
// Handle scroll issue when dynamically removing items (see #133)
|
|
169
|
-
// This also fixes first item's active state on Android
|
|
170
|
-
// Because 'initialScrollIndex' apparently doesn't trigger scroll
|
|
171
|
-
if (this._previousItemsLength > itemsLength) {
|
|
172
|
-
this._hackActiveSlideAnimation(nextActiveItem, null, true);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (hasNewSliderWidth || hasNewSliderHeight || hasNewItemWidth || hasNewItemHeight) {
|
|
176
|
-
this._snapToItem(nextActiveItem, false, false, false, false);
|
|
177
|
-
}
|
|
178
|
-
} else if (nextFirstItem !== this._previousFirstItem && nextFirstItem !== this._activeItem) {
|
|
179
|
-
this._activeItem = nextFirstItem;
|
|
180
|
-
this._previousFirstItem = nextFirstItem;
|
|
181
|
-
this._snapToItem(nextFirstItem, false, true, false, false);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (this.props.onScroll !== prevProps.onScroll) {
|
|
185
|
-
this._setScrollHandler(this.props);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
componentWillUnmount () {
|
|
190
|
-
this._mounted = false;
|
|
191
|
-
this.stopAutoplay();
|
|
192
|
-
clearTimeout(this._apparitionTimeout);
|
|
193
|
-
clearTimeout(this._hackSlideAnimationTimeout);
|
|
194
|
-
clearTimeout(this._enableAutoplayTimeout);
|
|
195
|
-
clearTimeout(this._autoplayTimeout);
|
|
196
|
-
clearTimeout(this._snapNoMomentumTimeout);
|
|
197
|
-
clearTimeout(this._edgeItemTimeout);
|
|
198
|
-
clearTimeout(this._lockScrollTimeout);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
get realIndex () {
|
|
202
|
-
return this._activeItem;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
get currentIndex () {
|
|
206
|
-
return this._getDataIndex(this._activeItem);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
get currentScrollPosition () {
|
|
210
|
-
return this._currentContentOffset;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
_setScrollHandler(props) {
|
|
214
|
-
// Native driver for scroll events
|
|
215
|
-
const scrollEventConfig = {
|
|
216
|
-
listener: this._onScroll,
|
|
217
|
-
useNativeDriver: true,
|
|
218
|
-
};
|
|
219
|
-
this._scrollPos = new Animated.Value(0);
|
|
220
|
-
const argMapping = props.vertical
|
|
221
|
-
? [{ nativeEvent: { contentOffset: { y: this._scrollPos } } }]
|
|
222
|
-
: [{ nativeEvent: { contentOffset: { x: this._scrollPos } } }];
|
|
223
|
-
|
|
224
|
-
if (props.onScroll && Array.isArray(props.onScroll._argMapping)) {
|
|
225
|
-
// Because of a react-native issue https://github.com/facebook/react-native/issues/13294
|
|
226
|
-
argMapping.pop();
|
|
227
|
-
const [ argMap ] = props.onScroll._argMapping;
|
|
228
|
-
if (argMap && argMap.nativeEvent && argMap.nativeEvent.contentOffset) {
|
|
229
|
-
// Shares the same animated value passed in props
|
|
230
|
-
this._scrollPos =
|
|
231
|
-
argMap.nativeEvent.contentOffset.x ||
|
|
232
|
-
argMap.nativeEvent.contentOffset.y ||
|
|
233
|
-
this._scrollPos;
|
|
234
|
-
}
|
|
235
|
-
argMapping.push(...props.onScroll._argMapping);
|
|
236
|
-
}
|
|
237
|
-
this._onScrollHandler = Animated.event(
|
|
238
|
-
argMapping,
|
|
239
|
-
scrollEventConfig
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
_needsScrollView () {
|
|
244
|
-
const { useScrollView } = this.props;
|
|
245
|
-
return useScrollView || !Animated.FlatList || this._shouldUseStackLayout() || this._shouldUseTinderLayout();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
_needsRTLAdaptations () {
|
|
249
|
-
const { vertical } = this.props;
|
|
250
|
-
return IS_RTL && !IS_IOS && !vertical;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
_canLockScroll () {
|
|
254
|
-
const { scrollEnabled, enableMomentum, lockScrollWhileSnapping } = this.props;
|
|
255
|
-
return scrollEnabled && !enableMomentum && lockScrollWhileSnapping;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
_enableLoop () {
|
|
259
|
-
const { data, enableSnap, loop } = this.props;
|
|
260
|
-
return enableSnap && loop && data && data.length && data.length > 1;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
_shouldAnimateSlides (props = this.props) {
|
|
264
|
-
const { inactiveSlideOpacity, inactiveSlideScale, scrollInterpolator, slideInterpolatedStyle } = props;
|
|
265
|
-
return inactiveSlideOpacity < 1 ||
|
|
266
|
-
inactiveSlideScale < 1 ||
|
|
267
|
-
!!scrollInterpolator ||
|
|
268
|
-
!!slideInterpolatedStyle ||
|
|
269
|
-
this._shouldUseShiftLayout() ||
|
|
270
|
-
this._shouldUseStackLayout() ||
|
|
271
|
-
this._shouldUseTinderLayout();
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
_shouldUseCustomAnimation () {
|
|
275
|
-
const { activeAnimationOptions } = this.props;
|
|
276
|
-
return !!activeAnimationOptions && !this._shouldUseStackLayout() && !this._shouldUseTinderLayout();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
_shouldUseShiftLayout () {
|
|
280
|
-
const { inactiveSlideShift, layout } = this.props;
|
|
281
|
-
return layout === 'default' && inactiveSlideShift !== 0;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
_shouldUseStackLayout () {
|
|
285
|
-
return this.props.layout === 'stack';
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
_shouldUseTinderLayout () {
|
|
289
|
-
return this.props.layout === 'tinder';
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
_getCustomData (props = this.props) {
|
|
293
|
-
const { data, loopClonesPerSide } = props;
|
|
294
|
-
const dataLength = data && data.length;
|
|
295
|
-
|
|
296
|
-
if (!dataLength) {
|
|
297
|
-
return [];
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (!this._enableLoop()) {
|
|
301
|
-
return data;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
let previousItems = [];
|
|
305
|
-
let nextItems = [];
|
|
306
|
-
|
|
307
|
-
if (loopClonesPerSide > dataLength) {
|
|
308
|
-
const dataMultiplier = Math.floor(loopClonesPerSide / dataLength);
|
|
309
|
-
const remainder = loopClonesPerSide % dataLength;
|
|
310
|
-
|
|
311
|
-
for (let i = 0; i < dataMultiplier; i++) {
|
|
312
|
-
previousItems.push(...data);
|
|
313
|
-
nextItems.push(...data);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
previousItems.unshift(...data.slice(-remainder));
|
|
317
|
-
nextItems.push(...data.slice(0, remainder));
|
|
318
|
-
} else {
|
|
319
|
-
previousItems = data.slice(-loopClonesPerSide);
|
|
320
|
-
nextItems = data.slice(0, loopClonesPerSide);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return previousItems.concat(data, nextItems);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
_getCustomDataLength (props = this.props) {
|
|
327
|
-
const { data, loopClonesPerSide } = props;
|
|
328
|
-
const dataLength = data && data.length;
|
|
329
|
-
|
|
330
|
-
if (!dataLength) {
|
|
331
|
-
return 0;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return this._enableLoop() ? dataLength + (2 * loopClonesPerSide) : dataLength;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
_getCustomIndex (index, props = this.props) {
|
|
338
|
-
const itemsLength = this._getCustomDataLength(props);
|
|
339
|
-
|
|
340
|
-
if (!itemsLength || (!index && index !== 0)) {
|
|
341
|
-
return 0;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return this._needsRTLAdaptations() ? itemsLength - index - 1 : index;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
_getDataIndex (index) {
|
|
348
|
-
const { data, loopClonesPerSide } = this.props;
|
|
349
|
-
const dataLength = data && data.length;
|
|
350
|
-
|
|
351
|
-
if (!this._enableLoop() || !dataLength) {
|
|
352
|
-
return index;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
if (index >= dataLength + loopClonesPerSide) {
|
|
356
|
-
return loopClonesPerSide > dataLength ?
|
|
357
|
-
(index - loopClonesPerSide) % dataLength :
|
|
358
|
-
index - dataLength - loopClonesPerSide;
|
|
359
|
-
} else if (index < loopClonesPerSide) {
|
|
360
|
-
// TODO: is there a simpler way of determining the interpolated index?
|
|
361
|
-
if (loopClonesPerSide > dataLength) {
|
|
362
|
-
const baseDataIndexes = [];
|
|
363
|
-
const dataIndexes = [];
|
|
364
|
-
const dataMultiplier = Math.floor(loopClonesPerSide / dataLength);
|
|
365
|
-
const remainder = loopClonesPerSide % dataLength;
|
|
366
|
-
|
|
367
|
-
for (let i = 0; i < dataLength; i++) {
|
|
368
|
-
baseDataIndexes.push(i);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
for (let j = 0; j < dataMultiplier; j++) {
|
|
372
|
-
dataIndexes.push(...baseDataIndexes);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
dataIndexes.unshift(...baseDataIndexes.slice(-remainder));
|
|
376
|
-
return dataIndexes[index];
|
|
377
|
-
} else {
|
|
378
|
-
return index + dataLength - loopClonesPerSide;
|
|
379
|
-
}
|
|
380
|
-
} else {
|
|
381
|
-
return index - loopClonesPerSide;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Used with `snapToItem()` and 'PaginationDot'
|
|
386
|
-
_getPositionIndex (index) {
|
|
387
|
-
const { loop, loopClonesPerSide } = this.props;
|
|
388
|
-
return loop ? index + loopClonesPerSide : index;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
_getFirstItem (index, props = this.props) {
|
|
392
|
-
const { loopClonesPerSide } = props;
|
|
393
|
-
const itemsLength = this._getCustomDataLength(props);
|
|
394
|
-
|
|
395
|
-
if (!itemsLength || index > itemsLength - 1 || index < 0) {
|
|
396
|
-
return 0;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return this._enableLoop() ? index + loopClonesPerSide : index;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
_getWrappedRef () {
|
|
403
|
-
if (this._carouselRef && (
|
|
404
|
-
(this._needsScrollView() && this._carouselRef.scrollTo) ||
|
|
405
|
-
(!this._needsScrollView() && this._carouselRef.scrollToOffset)
|
|
406
|
-
)) {
|
|
407
|
-
return this._carouselRef;
|
|
408
|
-
}
|
|
409
|
-
// https://github.com/facebook/react-native/issues/10635
|
|
410
|
-
// https://stackoverflow.com/a/48786374/8412141
|
|
411
|
-
return this._carouselRef && this._carouselRef.getNode && this._carouselRef.getNode();
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
_getScrollEnabled () {
|
|
415
|
-
return this._scrollEnabled;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
_setScrollEnabled (scrollEnabled = true) {
|
|
419
|
-
const wrappedRef = this._getWrappedRef();
|
|
420
|
-
|
|
421
|
-
if (!wrappedRef || !wrappedRef.setNativeProps) {
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// 'setNativeProps()' is used instead of 'setState()' because the latter
|
|
426
|
-
// really takes a toll on Android behavior when momentum is disabled
|
|
427
|
-
wrappedRef.setNativeProps({ scrollEnabled });
|
|
428
|
-
this._scrollEnabled = scrollEnabled;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
_getKeyExtractor (item, index) {
|
|
432
|
-
return this._needsScrollView() ? `scrollview-item-${index}` : `flatlist-item-${index}`;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
_getScrollOffset (event) {
|
|
436
|
-
const { vertical } = this.props;
|
|
437
|
-
return (event && event.nativeEvent && event.nativeEvent.contentOffset &&
|
|
438
|
-
event.nativeEvent.contentOffset[vertical ? 'y' : 'x']) || 0;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
_getContainerInnerMargin (opposite = false) {
|
|
442
|
-
const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
|
|
443
|
-
|
|
444
|
-
if ((activeSlideAlignment === 'start' && !opposite) ||
|
|
445
|
-
(activeSlideAlignment === 'end' && opposite)) {
|
|
446
|
-
return 0;
|
|
447
|
-
} else if ((activeSlideAlignment === 'end' && !opposite) ||
|
|
448
|
-
(activeSlideAlignment === 'start' && opposite)) {
|
|
449
|
-
return vertical ? sliderHeight - itemHeight : sliderWidth - itemWidth;
|
|
450
|
-
} else {
|
|
451
|
-
return vertical ? (sliderHeight - itemHeight) / 2 : (sliderWidth - itemWidth) / 2;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
_getViewportOffset () {
|
|
456
|
-
const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
|
|
457
|
-
|
|
458
|
-
if (activeSlideAlignment === 'start') {
|
|
459
|
-
return vertical ? itemHeight / 2 : itemWidth / 2;
|
|
460
|
-
} else if (activeSlideAlignment === 'end') {
|
|
461
|
-
return vertical ?
|
|
462
|
-
sliderHeight - (itemHeight / 2) :
|
|
463
|
-
sliderWidth - (itemWidth / 2);
|
|
464
|
-
} else {
|
|
465
|
-
return vertical ? sliderHeight / 2 : sliderWidth / 2;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
_getCenter (offset) {
|
|
470
|
-
return offset + this._getViewportOffset() - this._getContainerInnerMargin();
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
_getActiveItem (offset) {
|
|
474
|
-
const { activeSlideOffset, swipeThreshold } = this.props;
|
|
475
|
-
const center = this._getCenter(offset);
|
|
476
|
-
const centerOffset = activeSlideOffset || swipeThreshold;
|
|
477
|
-
|
|
478
|
-
for (let i = 0; i < this._positions.length; i++) {
|
|
479
|
-
const { start, end } = this._positions[i];
|
|
480
|
-
if (center + centerOffset >= start && center - centerOffset <= end) {
|
|
481
|
-
return i;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
const lastIndex = this._positions.length - 1;
|
|
486
|
-
if (this._positions[lastIndex] && center - centerOffset > this._positions[lastIndex].end) {
|
|
487
|
-
return lastIndex;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
return 0;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
_initPositionsAndInterpolators (props = this.props) {
|
|
494
|
-
const { data, itemWidth, itemHeight, scrollInterpolator, vertical } = props;
|
|
495
|
-
const sizeRef = vertical ? itemHeight : itemWidth;
|
|
496
|
-
|
|
497
|
-
if (!data || !data.length) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
let interpolators = [];
|
|
502
|
-
this._positions = [];
|
|
503
|
-
|
|
504
|
-
this._getCustomData(props).forEach((itemData, index) => {
|
|
505
|
-
const _index = this._getCustomIndex(index, props);
|
|
506
|
-
let animatedValue;
|
|
507
|
-
|
|
508
|
-
this._positions[index] = {
|
|
509
|
-
start: index * sizeRef,
|
|
510
|
-
end: index * sizeRef + sizeRef
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
if (!this._shouldAnimateSlides(props)) {
|
|
514
|
-
animatedValue = new Animated.Value(1);
|
|
515
|
-
} else if (this._shouldUseCustomAnimation()) {
|
|
516
|
-
animatedValue = new Animated.Value(_index === this._activeItem ? 1 : 0);
|
|
517
|
-
} else {
|
|
518
|
-
let interpolator;
|
|
519
|
-
|
|
520
|
-
if (scrollInterpolator) {
|
|
521
|
-
interpolator = scrollInterpolator(_index, props);
|
|
522
|
-
} else if (this._shouldUseStackLayout()) {
|
|
523
|
-
interpolator = stackScrollInterpolator(_index, props);
|
|
524
|
-
} else if (this._shouldUseTinderLayout()) {
|
|
525
|
-
interpolator = tinderScrollInterpolator(_index, props);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
if (!interpolator || !interpolator.inputRange || !interpolator.outputRange) {
|
|
529
|
-
interpolator = defaultScrollInterpolator(_index, props);
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
animatedValue = this._scrollPos.interpolate({
|
|
533
|
-
...interpolator,
|
|
534
|
-
extrapolate: 'clamp'
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
interpolators.push(animatedValue);
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
this.setState({ interpolators });
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
_getSlideAnimation (index, toValue) {
|
|
545
|
-
const { interpolators } = this.state;
|
|
546
|
-
const { activeAnimationType, activeAnimationOptions } = this.props;
|
|
547
|
-
|
|
548
|
-
const animatedValue = interpolators && interpolators[index];
|
|
549
|
-
|
|
550
|
-
if (!animatedValue && animatedValue !== 0) {
|
|
551
|
-
return null;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
const animationCommonOptions = {
|
|
555
|
-
isInteraction: false,
|
|
556
|
-
useNativeDriver: true,
|
|
557
|
-
...activeAnimationOptions,
|
|
558
|
-
toValue: toValue
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
return Animated.parallel([
|
|
562
|
-
Animated['timing'](
|
|
563
|
-
animatedValue,
|
|
564
|
-
{ ...animationCommonOptions, easing: Easing.linear }
|
|
565
|
-
),
|
|
566
|
-
Animated[activeAnimationType](
|
|
567
|
-
animatedValue,
|
|
568
|
-
{ ...animationCommonOptions }
|
|
569
|
-
)
|
|
570
|
-
]);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
_playCustomSlideAnimation (current, next) {
|
|
574
|
-
const { interpolators } = this.state;
|
|
575
|
-
const itemsLength = this._getCustomDataLength();
|
|
576
|
-
const _currentIndex = this._getCustomIndex(current);
|
|
577
|
-
const _currentDataIndex = this._getDataIndex(_currentIndex);
|
|
578
|
-
const _nextIndex = this._getCustomIndex(next);
|
|
579
|
-
const _nextDataIndex = this._getDataIndex(_nextIndex);
|
|
580
|
-
let animations = [];
|
|
581
|
-
|
|
582
|
-
// Keep animations in sync when looping
|
|
583
|
-
if (this._enableLoop()) {
|
|
584
|
-
for (let i = 0; i < itemsLength; i++) {
|
|
585
|
-
if (this._getDataIndex(i) === _currentDataIndex && interpolators[i]) {
|
|
586
|
-
animations.push(this._getSlideAnimation(i, 0));
|
|
587
|
-
} else if (this._getDataIndex(i) === _nextDataIndex && interpolators[i]) {
|
|
588
|
-
animations.push(this._getSlideAnimation(i, 1));
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
} else {
|
|
592
|
-
if (interpolators[current]) {
|
|
593
|
-
animations.push(this._getSlideAnimation(current, 0));
|
|
594
|
-
}
|
|
595
|
-
if (interpolators[next]) {
|
|
596
|
-
animations.push(this._getSlideAnimation(next, 1));
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
Animated.parallel(animations, { stopTogether: false }).start();
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
_hackActiveSlideAnimation (index, goTo, force = false) {
|
|
604
|
-
const { data } = this.props;
|
|
605
|
-
|
|
606
|
-
if (!this._mounted || !this._carouselRef || !this._positions[index] || (!force && this._enableLoop())) {
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
const offset = this._positions[index] && this._positions[index].start;
|
|
611
|
-
|
|
612
|
-
if (!offset && offset !== 0) {
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
const itemsLength = data && data.length;
|
|
617
|
-
const direction = goTo || itemsLength === 1 ? 'start' : 'end';
|
|
618
|
-
|
|
619
|
-
this._scrollTo(offset + (direction === 'start' ? -1 : 1), false);
|
|
620
|
-
|
|
621
|
-
clearTimeout(this._hackSlideAnimationTimeout);
|
|
622
|
-
this._hackSlideAnimationTimeout = setTimeout(() => {
|
|
623
|
-
this._scrollTo(offset, false);
|
|
624
|
-
}, 50); // works randomly when set to '0'
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
_lockScroll () {
|
|
628
|
-
const { lockScrollTimeoutDuration } = this.props;
|
|
629
|
-
clearTimeout(this._lockScrollTimeout);
|
|
630
|
-
this._lockScrollTimeout = setTimeout(() => {
|
|
631
|
-
this._releaseScroll();
|
|
632
|
-
}, lockScrollTimeoutDuration);
|
|
633
|
-
this._setScrollEnabled(false);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
_releaseScroll () {
|
|
637
|
-
clearTimeout(this._lockScrollTimeout);
|
|
638
|
-
this._setScrollEnabled(true);
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
_repositionScroll (index) {
|
|
642
|
-
const { data, loopClonesPerSide } = this.props;
|
|
643
|
-
const dataLength = data && data.length;
|
|
644
|
-
|
|
645
|
-
if (!this._enableLoop() || !dataLength ||
|
|
646
|
-
(index >= loopClonesPerSide && index < dataLength + loopClonesPerSide)) {
|
|
647
|
-
return;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
let repositionTo = index;
|
|
651
|
-
|
|
652
|
-
if (index >= dataLength + loopClonesPerSide) {
|
|
653
|
-
repositionTo = index - dataLength;
|
|
654
|
-
} else if (index < loopClonesPerSide) {
|
|
655
|
-
repositionTo = index + dataLength;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
this._snapToItem(repositionTo, false, false, false, false);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
_scrollTo (offset, animated = true) {
|
|
662
|
-
const { vertical } = this.props;
|
|
663
|
-
const wrappedRef = this._getWrappedRef();
|
|
664
|
-
|
|
665
|
-
if (!this._mounted || !wrappedRef) {
|
|
666
|
-
return;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
const specificOptions = this._needsScrollView() ? {
|
|
670
|
-
x: vertical ? 0 : offset,
|
|
671
|
-
y: vertical ? offset : 0
|
|
672
|
-
} : {
|
|
673
|
-
offset
|
|
674
|
-
};
|
|
675
|
-
const options = {
|
|
676
|
-
...specificOptions,
|
|
677
|
-
animated
|
|
678
|
-
};
|
|
679
|
-
|
|
680
|
-
if (this._needsScrollView()) {
|
|
681
|
-
wrappedRef.scrollTo(options);
|
|
682
|
-
} else {
|
|
683
|
-
wrappedRef.scrollToOffset(options);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
_onScroll (event) {
|
|
688
|
-
const { callbackOffsetMargin, enableMomentum, onScroll } = this.props;
|
|
689
|
-
|
|
690
|
-
const scrollOffset = event ? this._getScrollOffset(event) : this._currentContentOffset;
|
|
691
|
-
const nextActiveItem = this._getActiveItem(scrollOffset);
|
|
692
|
-
const itemReached = nextActiveItem === this._itemToSnapTo;
|
|
693
|
-
const scrollConditions =
|
|
694
|
-
scrollOffset >= this._scrollOffsetRef - callbackOffsetMargin &&
|
|
695
|
-
scrollOffset <= this._scrollOffsetRef + callbackOffsetMargin;
|
|
696
|
-
|
|
697
|
-
this._currentContentOffset = scrollOffset;
|
|
698
|
-
this._onScrollTriggered = true;
|
|
699
|
-
this._lastScrollDate = Date.now();
|
|
700
|
-
|
|
701
|
-
if (this._activeItem !== nextActiveItem && this._shouldUseCustomAnimation()) {
|
|
702
|
-
this._playCustomSlideAnimation(this._activeItem, nextActiveItem);
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
if (enableMomentum) {
|
|
706
|
-
clearTimeout(this._snapNoMomentumTimeout);
|
|
707
|
-
|
|
708
|
-
if (this._activeItem !== nextActiveItem) {
|
|
709
|
-
this._activeItem = nextActiveItem;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (itemReached) {
|
|
713
|
-
if (this._canFireBeforeCallback) {
|
|
714
|
-
this._onBeforeSnap(this._getDataIndex(nextActiveItem));
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
if (scrollConditions && this._canFireCallback) {
|
|
718
|
-
this._onSnap(this._getDataIndex(nextActiveItem));
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
} else if (this._activeItem !== nextActiveItem && itemReached) {
|
|
722
|
-
if (this._canFireBeforeCallback) {
|
|
723
|
-
this._onBeforeSnap(this._getDataIndex(nextActiveItem));
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
if (scrollConditions) {
|
|
727
|
-
this._activeItem = nextActiveItem;
|
|
728
|
-
|
|
729
|
-
if (this._canLockScroll()) {
|
|
730
|
-
this._releaseScroll();
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (this._canFireCallback) {
|
|
734
|
-
this._onSnap(this._getDataIndex(nextActiveItem));
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
if (nextActiveItem === this._itemToSnapTo &&
|
|
740
|
-
scrollOffset === this._scrollOffsetRef) {
|
|
741
|
-
this._repositionScroll(nextActiveItem);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
if (typeof onScroll === "function" && event) {
|
|
745
|
-
onScroll(event);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
_onStartShouldSetResponderCapture (event) {
|
|
750
|
-
const { onStartShouldSetResponderCapture } = this.props;
|
|
751
|
-
|
|
752
|
-
if (onStartShouldSetResponderCapture) {
|
|
753
|
-
onStartShouldSetResponderCapture(event);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
return this._getScrollEnabled();
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
_onTouchStart () {
|
|
760
|
-
const { onTouchStart } = this.props
|
|
761
|
-
|
|
762
|
-
// `onTouchStart` is fired even when `scrollEnabled` is set to `false`
|
|
763
|
-
if (this._getScrollEnabled() !== false && this._autoplaying) {
|
|
764
|
-
this.pauseAutoPlay();
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
if (onTouchStart) {
|
|
768
|
-
onTouchStart()
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
_onTouchEnd () {
|
|
773
|
-
const { onTouchEnd } = this.props
|
|
774
|
-
|
|
775
|
-
if (this._getScrollEnabled() !== false && this._autoplay && !this._autoplaying) {
|
|
776
|
-
// This event is buggy on Android, so a fallback is provided in _onScrollEnd()
|
|
777
|
-
this.startAutoplay();
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
if (onTouchEnd) {
|
|
781
|
-
onTouchEnd()
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
// Used when `enableSnap` is ENABLED
|
|
786
|
-
_onScrollBeginDrag (event) {
|
|
787
|
-
const { onScrollBeginDrag } = this.props;
|
|
788
|
-
|
|
789
|
-
if (!this._getScrollEnabled()) {
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
this._scrollStartOffset = this._getScrollOffset(event);
|
|
794
|
-
this._scrollStartActive = this._getActiveItem(this._scrollStartOffset);
|
|
795
|
-
this._ignoreNextMomentum = false;
|
|
796
|
-
// this._canFireCallback = false;
|
|
797
|
-
|
|
798
|
-
if (onScrollBeginDrag) {
|
|
799
|
-
onScrollBeginDrag(event);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
// Used when `enableMomentum` is DISABLED
|
|
804
|
-
_onScrollEndDrag (event) {
|
|
805
|
-
const { onScrollEndDrag } = this.props;
|
|
806
|
-
|
|
807
|
-
if (this._carouselRef) {
|
|
808
|
-
this._onScrollEnd && this._onScrollEnd();
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
if (onScrollEndDrag) {
|
|
812
|
-
onScrollEndDrag(event);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// Used when `enableMomentum` is ENABLED
|
|
817
|
-
_onMomentumScrollEnd (event) {
|
|
818
|
-
const { onMomentumScrollEnd } = this.props;
|
|
819
|
-
|
|
820
|
-
if (this._carouselRef) {
|
|
821
|
-
this._onScrollEnd && this._onScrollEnd();
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
if (onMomentumScrollEnd) {
|
|
825
|
-
onMomentumScrollEnd(event);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
_onScrollEnd (event) {
|
|
830
|
-
const { autoplayDelay, enableSnap } = this.props;
|
|
831
|
-
|
|
832
|
-
if (this._ignoreNextMomentum) {
|
|
833
|
-
// iOS fix
|
|
834
|
-
this._ignoreNextMomentum = false;
|
|
835
|
-
return;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
if (this._currentContentOffset === this._scrollEndOffset) {
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
this._scrollEndOffset = this._currentContentOffset;
|
|
843
|
-
this._scrollEndActive = this._getActiveItem(this._scrollEndOffset);
|
|
844
|
-
|
|
845
|
-
if (enableSnap) {
|
|
846
|
-
this._snapScroll(this._scrollEndOffset - this._scrollStartOffset);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
// The touchEnd event is buggy on Android, so this will serve as a fallback whenever needed
|
|
850
|
-
// https://github.com/facebook/react-native/issues/9439
|
|
851
|
-
if (this._autoplay && !this._autoplaying) {
|
|
852
|
-
clearTimeout(this._enableAutoplayTimeout);
|
|
853
|
-
this._enableAutoplayTimeout = setTimeout(() => {
|
|
854
|
-
this.startAutoplay();
|
|
855
|
-
}, autoplayDelay + 50);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
// Due to a bug, this event is only fired on iOS
|
|
860
|
-
// https://github.com/facebook/react-native/issues/6791
|
|
861
|
-
// it's fine since we're only fixing an iOS bug in it, so ...
|
|
862
|
-
_onTouchRelease (event) {
|
|
863
|
-
const { enableMomentum } = this.props;
|
|
864
|
-
|
|
865
|
-
if (enableMomentum && IS_IOS) {
|
|
866
|
-
clearTimeout(this._snapNoMomentumTimeout);
|
|
867
|
-
this._snapNoMomentumTimeout = setTimeout(() => {
|
|
868
|
-
this._snapToItem(this._activeItem);
|
|
869
|
-
}, 100);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
_onLayout (event) {
|
|
874
|
-
const { onLayout } = this.props;
|
|
875
|
-
|
|
876
|
-
// Prevent unneeded actions during the first 'onLayout' (triggered on init)
|
|
877
|
-
if (this._onLayoutInitDone) {
|
|
878
|
-
this._initPositionsAndInterpolators();
|
|
879
|
-
this._snapToItem(this._activeItem, false, false, false, false);
|
|
880
|
-
} else {
|
|
881
|
-
this._onLayoutInitDone = true;
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
if (onLayout) {
|
|
885
|
-
onLayout(event);
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
_snapScroll (delta) {
|
|
890
|
-
const { swipeThreshold } = this.props;
|
|
891
|
-
|
|
892
|
-
// When using momentum and releasing the touch with
|
|
893
|
-
// no velocity, scrollEndActive will be undefined (iOS)
|
|
894
|
-
if (!this._scrollEndActive && this._scrollEndActive !== 0 && IS_IOS) {
|
|
895
|
-
this._scrollEndActive = this._scrollStartActive;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
if (this._scrollStartActive !== this._scrollEndActive) {
|
|
899
|
-
// Snap to the new active item
|
|
900
|
-
this._snapToItem(this._scrollEndActive);
|
|
901
|
-
} else {
|
|
902
|
-
// Snap depending on delta
|
|
903
|
-
if (delta > 0) {
|
|
904
|
-
if (delta > swipeThreshold) {
|
|
905
|
-
this._snapToItem(this._scrollStartActive + 1);
|
|
906
|
-
} else {
|
|
907
|
-
this._snapToItem(this._scrollEndActive);
|
|
908
|
-
}
|
|
909
|
-
} else if (delta < 0) {
|
|
910
|
-
if (delta < -swipeThreshold) {
|
|
911
|
-
this._snapToItem(this._scrollStartActive - 1);
|
|
912
|
-
} else {
|
|
913
|
-
this._snapToItem(this._scrollEndActive);
|
|
914
|
-
}
|
|
915
|
-
} else {
|
|
916
|
-
// Snap to current
|
|
917
|
-
this._snapToItem(this._scrollEndActive);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
_snapToItem (index, animated = true, fireCallback = true, initial = false, lockScroll = true) {
|
|
923
|
-
const { enableMomentum, onSnapToItem, onBeforeSnapToItem } = this.props;
|
|
924
|
-
const itemsLength = this._getCustomDataLength();
|
|
925
|
-
const wrappedRef = this._getWrappedRef();
|
|
926
|
-
|
|
927
|
-
if (!itemsLength || !wrappedRef) {
|
|
928
|
-
return;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
if (!index || index < 0) {
|
|
932
|
-
index = 0;
|
|
933
|
-
} else if (itemsLength > 0 && index >= itemsLength) {
|
|
934
|
-
index = itemsLength - 1;
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
if (index !== this._previousActiveItem) {
|
|
938
|
-
this._previousActiveItem = index;
|
|
939
|
-
|
|
940
|
-
// Placed here to allow overscrolling for edges items
|
|
941
|
-
if (lockScroll && this._canLockScroll()) {
|
|
942
|
-
this._lockScroll();
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
if (fireCallback) {
|
|
946
|
-
if (onBeforeSnapToItem) {
|
|
947
|
-
this._canFireBeforeCallback = true;
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
if (onSnapToItem) {
|
|
951
|
-
this._canFireCallback = true;
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
this._itemToSnapTo = index;
|
|
957
|
-
this._scrollOffsetRef = this._positions[index] && this._positions[index].start;
|
|
958
|
-
this._onScrollTriggered = false;
|
|
959
|
-
|
|
960
|
-
if (!this._scrollOffsetRef && this._scrollOffsetRef !== 0) {
|
|
961
|
-
return;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
this._scrollTo(this._scrollOffsetRef, animated);
|
|
965
|
-
|
|
966
|
-
this._scrollEndOffset = this._currentContentOffset;
|
|
967
|
-
|
|
968
|
-
if (enableMomentum) {
|
|
969
|
-
// iOS fix, check the note in the constructor
|
|
970
|
-
if (!initial) {
|
|
971
|
-
this._ignoreNextMomentum = true;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
// When momentum is enabled and the user is overscrolling or swiping very quickly,
|
|
975
|
-
// 'onScroll' is not going to be triggered for edge items. Then callback won't be
|
|
976
|
-
// fired and loop won't work since the scrollview is not going to be repositioned.
|
|
977
|
-
// As a workaround, '_onScroll()' will be called manually for these items if a given
|
|
978
|
-
// condition hasn't been met after a small delay.
|
|
979
|
-
// WARNING: this is ok only when relying on 'momentumScrollEnd', not with 'scrollEndDrag'
|
|
980
|
-
if (index === 0 || index === itemsLength - 1) {
|
|
981
|
-
clearTimeout(this._edgeItemTimeout);
|
|
982
|
-
this._edgeItemTimeout = setTimeout(() => {
|
|
983
|
-
if (!initial && index === this._activeItem && !this._onScrollTriggered) {
|
|
984
|
-
this._onScroll();
|
|
985
|
-
}
|
|
986
|
-
}, 250);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
_onBeforeSnap (index) {
|
|
992
|
-
const { onBeforeSnapToItem } = this.props;
|
|
993
|
-
|
|
994
|
-
if (!this._carouselRef) {
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
this._canFireBeforeCallback = false;
|
|
999
|
-
onBeforeSnapToItem && onBeforeSnapToItem(index);
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
_onSnap (index) {
|
|
1003
|
-
const { onSnapToItem } = this.props;
|
|
1004
|
-
|
|
1005
|
-
if (!this._carouselRef) {
|
|
1006
|
-
return;
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
this._canFireCallback = false;
|
|
1010
|
-
onSnapToItem && onSnapToItem(index);
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
startAutoplay () {
|
|
1014
|
-
const { autoplayInterval, autoplayDelay } = this.props;
|
|
1015
|
-
this._autoplay = true;
|
|
1016
|
-
|
|
1017
|
-
if (this._autoplaying) {
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
clearTimeout(this._autoplayTimeout);
|
|
1022
|
-
this._autoplayTimeout = setTimeout(() => {
|
|
1023
|
-
this._autoplaying = true;
|
|
1024
|
-
this._autoplayInterval = setInterval(() => {
|
|
1025
|
-
if (this._autoplaying) {
|
|
1026
|
-
this.snapToNext();
|
|
1027
|
-
}
|
|
1028
|
-
}, autoplayInterval);
|
|
1029
|
-
}, autoplayDelay);
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
pauseAutoPlay () {
|
|
1033
|
-
this._autoplaying = false;
|
|
1034
|
-
clearTimeout(this._autoplayTimeout);
|
|
1035
|
-
clearTimeout(this._enableAutoplayTimeout);
|
|
1036
|
-
clearInterval(this._autoplayInterval);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
stopAutoplay () {
|
|
1040
|
-
this._autoplay = false;
|
|
1041
|
-
this.pauseAutoPlay();
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
snapToItem (index, animated = true, fireCallback = true) {
|
|
1045
|
-
if (!index || index < 0) {
|
|
1046
|
-
index = 0;
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
const positionIndex = this._getPositionIndex(index);
|
|
1050
|
-
|
|
1051
|
-
if (positionIndex === this._activeItem) {
|
|
1052
|
-
return;
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
this._snapToItem(positionIndex, animated, fireCallback);
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
snapToNext (animated = true, fireCallback = true) {
|
|
1059
|
-
const itemsLength = this._getCustomDataLength();
|
|
1060
|
-
|
|
1061
|
-
let newIndex = this._activeItem + 1;
|
|
1062
|
-
if (newIndex > itemsLength - 1) {
|
|
1063
|
-
if (!this._enableLoop()) {
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
newIndex = 0;
|
|
1067
|
-
}
|
|
1068
|
-
this._snapToItem(newIndex, animated, fireCallback);
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
snapToPrev (animated = true, fireCallback = true) {
|
|
1072
|
-
const itemsLength = this._getCustomDataLength();
|
|
1073
|
-
|
|
1074
|
-
let newIndex = this._activeItem - 1;
|
|
1075
|
-
if (newIndex < 0) {
|
|
1076
|
-
if (!this._enableLoop()) {
|
|
1077
|
-
return;
|
|
1078
|
-
}
|
|
1079
|
-
newIndex = itemsLength - 1;
|
|
1080
|
-
}
|
|
1081
|
-
this._snapToItem(newIndex, animated, fireCallback);
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
// https://github.com/facebook/react-native/issues/1831#issuecomment-231069668
|
|
1085
|
-
triggerRenderingHack (offset) {
|
|
1086
|
-
// Avoid messing with user scroll
|
|
1087
|
-
if (Date.now() - this._lastScrollDate < 500) {
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
const scrollPosition = this._currentContentOffset;
|
|
1092
|
-
if (!scrollPosition && scrollPosition !== 0) {
|
|
1093
|
-
return;
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
const scrollOffset = offset || (scrollPosition === 0 ? 1 : -1);
|
|
1097
|
-
this._scrollTo(scrollPosition + scrollOffset, false);
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
_getSlideInterpolatedStyle (index, animatedValue) {
|
|
1101
|
-
const { layoutCardOffset, slideInterpolatedStyle } = this.props;
|
|
1102
|
-
|
|
1103
|
-
if (slideInterpolatedStyle) {
|
|
1104
|
-
return slideInterpolatedStyle(index, animatedValue, this.props);
|
|
1105
|
-
} else if (this._shouldUseTinderLayout()) {
|
|
1106
|
-
return tinderAnimatedStyles(index, animatedValue, this.props, layoutCardOffset);
|
|
1107
|
-
} else if (this._shouldUseStackLayout()) {
|
|
1108
|
-
return stackAnimatedStyles(index, animatedValue, this.props, layoutCardOffset);
|
|
1109
|
-
} else if (this._shouldUseShiftLayout()) {
|
|
1110
|
-
return shiftAnimatedStyles(index, animatedValue, this.props);
|
|
1111
|
-
} else {
|
|
1112
|
-
return defaultAnimatedStyles(index, animatedValue, this.props);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
_renderItem ({ item, index }) {
|
|
1117
|
-
const { interpolators } = this.state;
|
|
1118
|
-
const {
|
|
1119
|
-
hasParallaxImages,
|
|
1120
|
-
itemWidth,
|
|
1121
|
-
itemHeight,
|
|
1122
|
-
keyExtractor,
|
|
1123
|
-
renderItem,
|
|
1124
|
-
sliderHeight,
|
|
1125
|
-
sliderWidth,
|
|
1126
|
-
slideStyle,
|
|
1127
|
-
vertical
|
|
1128
|
-
} = this.props;
|
|
1129
|
-
|
|
1130
|
-
const animatedValue = interpolators && interpolators[index];
|
|
1131
|
-
|
|
1132
|
-
if (!animatedValue && animatedValue !== 0) {
|
|
1133
|
-
return null;
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
const animate = this._shouldAnimateSlides();
|
|
1137
|
-
const Component = animate ? Animated.View : View;
|
|
1138
|
-
const animatedStyle = animate ? this._getSlideInterpolatedStyle(index, animatedValue) : {};
|
|
1139
|
-
|
|
1140
|
-
const parallaxProps = hasParallaxImages ? {
|
|
1141
|
-
scrollPosition: this._scrollPos,
|
|
1142
|
-
carouselRef: this._carouselRef,
|
|
1143
|
-
vertical,
|
|
1144
|
-
sliderWidth,
|
|
1145
|
-
sliderHeight,
|
|
1146
|
-
itemWidth,
|
|
1147
|
-
itemHeight
|
|
1148
|
-
} : undefined;
|
|
1149
|
-
|
|
1150
|
-
const mainDimension = vertical ? { height: itemHeight } : { width: itemWidth };
|
|
1151
|
-
const specificProps = this._needsScrollView() ? {
|
|
1152
|
-
key: keyExtractor ? keyExtractor(item, index) : this._getKeyExtractor(item, index)
|
|
1153
|
-
} : {};
|
|
1154
|
-
|
|
1155
|
-
return (
|
|
1156
|
-
<Component style={[mainDimension, slideStyle, animatedStyle]} pointerEvents={'box-none'} {...specificProps}>
|
|
1157
|
-
{ renderItem({ item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem) }, parallaxProps) }
|
|
1158
|
-
</Component>
|
|
1159
|
-
);
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
_getComponentOverridableProps () {
|
|
1163
|
-
const {
|
|
1164
|
-
enableMomentum,
|
|
1165
|
-
itemWidth,
|
|
1166
|
-
itemHeight,
|
|
1167
|
-
loopClonesPerSide,
|
|
1168
|
-
sliderWidth,
|
|
1169
|
-
sliderHeight,
|
|
1170
|
-
vertical
|
|
1171
|
-
} = this.props;
|
|
1172
|
-
|
|
1173
|
-
const visibleItems = Math.ceil(vertical ?
|
|
1174
|
-
sliderHeight / itemHeight :
|
|
1175
|
-
sliderWidth / itemWidth) + 1;
|
|
1176
|
-
const initialNumPerSide = this._enableLoop() ? loopClonesPerSide : 2;
|
|
1177
|
-
const initialNumToRender = visibleItems + (initialNumPerSide * 2);
|
|
1178
|
-
const maxToRenderPerBatch = 1 + (initialNumToRender * 2);
|
|
1179
|
-
const windowSize = maxToRenderPerBatch;
|
|
1180
|
-
|
|
1181
|
-
const specificProps = !this._needsScrollView() ? {
|
|
1182
|
-
initialNumToRender: initialNumToRender,
|
|
1183
|
-
maxToRenderPerBatch: maxToRenderPerBatch,
|
|
1184
|
-
windowSize: windowSize
|
|
1185
|
-
// updateCellsBatchingPeriod
|
|
1186
|
-
} : {};
|
|
1187
|
-
|
|
1188
|
-
return {
|
|
1189
|
-
decelerationRate: enableMomentum ? 0.9 : 'fast',
|
|
1190
|
-
showsHorizontalScrollIndicator: false,
|
|
1191
|
-
showsVerticalScrollIndicator: false,
|
|
1192
|
-
overScrollMode: 'never',
|
|
1193
|
-
automaticallyAdjustContentInsets: false,
|
|
1194
|
-
directionalLockEnabled: true,
|
|
1195
|
-
pinchGestureEnabled: false,
|
|
1196
|
-
scrollsToTop: false,
|
|
1197
|
-
removeClippedSubviews: !this._needsScrollView(),
|
|
1198
|
-
inverted: this._needsRTLAdaptations(),
|
|
1199
|
-
renderToHardwareTextureAndroid: true,
|
|
1200
|
-
...specificProps
|
|
1201
|
-
};
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
|
-
_getComponentStaticProps () {
|
|
1205
|
-
const { hideCarousel } = this.state;
|
|
1206
|
-
const {
|
|
1207
|
-
containerCustomStyle,
|
|
1208
|
-
contentContainerCustomStyle,
|
|
1209
|
-
keyExtractor,
|
|
1210
|
-
sliderWidth,
|
|
1211
|
-
sliderHeight,
|
|
1212
|
-
style,
|
|
1213
|
-
vertical
|
|
1214
|
-
} = this.props;
|
|
1215
|
-
|
|
1216
|
-
const containerStyle = [
|
|
1217
|
-
containerCustomStyle || style || {},
|
|
1218
|
-
hideCarousel ? { opacity: 0 } : {},
|
|
1219
|
-
vertical ?
|
|
1220
|
-
{ height: sliderHeight, flexDirection: 'column' } :
|
|
1221
|
-
// LTR hack; see https://github.com/facebook/react-native/issues/11960
|
|
1222
|
-
// and https://github.com/facebook/react-native/issues/13100#issuecomment-328986423
|
|
1223
|
-
{ width: sliderWidth, flexDirection: this._needsRTLAdaptations() ? 'row-reverse' : 'row' }
|
|
1224
|
-
];
|
|
1225
|
-
const contentContainerStyle = [
|
|
1226
|
-
vertical ? {
|
|
1227
|
-
paddingTop: this._getContainerInnerMargin(),
|
|
1228
|
-
paddingBottom: this._getContainerInnerMargin(true)
|
|
1229
|
-
} : {
|
|
1230
|
-
paddingLeft: this._getContainerInnerMargin(),
|
|
1231
|
-
paddingRight: this._getContainerInnerMargin(true)
|
|
1232
|
-
},
|
|
1233
|
-
contentContainerCustomStyle || {}
|
|
1234
|
-
];
|
|
1235
|
-
|
|
1236
|
-
const specificProps = !this._needsScrollView() ? {
|
|
1237
|
-
// extraData: this.state,
|
|
1238
|
-
renderItem: this._renderItem,
|
|
1239
|
-
numColumns: 1,
|
|
1240
|
-
keyExtractor: keyExtractor || this._getKeyExtractor
|
|
1241
|
-
} : {};
|
|
1242
|
-
|
|
1243
|
-
return {
|
|
1244
|
-
ref: c => this._carouselRef = c,
|
|
1245
|
-
data: this._getCustomData(),
|
|
1246
|
-
style: containerStyle,
|
|
1247
|
-
contentContainerStyle: contentContainerStyle,
|
|
1248
|
-
horizontal: !vertical,
|
|
1249
|
-
scrollEventThrottle: 1,
|
|
1250
|
-
onScroll: this._onScrollHandler,
|
|
1251
|
-
onScrollBeginDrag: this._onScrollBeginDrag,
|
|
1252
|
-
onScrollEndDrag: this._onScrollEndDrag,
|
|
1253
|
-
onMomentumScrollEnd: this._onMomentumScrollEnd,
|
|
1254
|
-
onResponderRelease: this._onTouchRelease,
|
|
1255
|
-
onStartShouldSetResponderCapture: this._onStartShouldSetResponderCapture,
|
|
1256
|
-
onTouchStart: this._onTouchStart,
|
|
1257
|
-
onTouchEnd: this._onScrollEnd,
|
|
1258
|
-
onLayout: this._onLayout,
|
|
1259
|
-
...specificProps
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
render () {
|
|
1264
|
-
const { data, renderItem, useScrollView } = this.props;
|
|
1265
|
-
|
|
1266
|
-
if (!data || !renderItem) {
|
|
1267
|
-
return null;
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
const props = {
|
|
1271
|
-
...this._getComponentOverridableProps(),
|
|
1272
|
-
...this.props,
|
|
1273
|
-
...this._getComponentStaticProps()
|
|
1274
|
-
};
|
|
1275
|
-
|
|
1276
|
-
const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView : Animated.ScrollView
|
|
1277
|
-
|
|
1278
|
-
return this._needsScrollView() ? (
|
|
1279
|
-
<ScrollViewComponent {...props}>
|
|
1280
|
-
{
|
|
1281
|
-
this._getCustomData().map((item, index) => {
|
|
1282
|
-
return this._renderItem({ item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem) });
|
|
1283
|
-
})
|
|
1284
|
-
}
|
|
1285
|
-
</ScrollViewComponent>
|
|
1286
|
-
) : (
|
|
1287
|
-
<Animated.FlatList {...props} />
|
|
1288
|
-
);
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
Carousel.propTypes = {
|
|
1293
|
-
data: PropTypes.array.isRequired,
|
|
1294
|
-
renderItem: PropTypes.func.isRequired,
|
|
1295
|
-
itemWidth: PropTypes.number, // required for horizontal carousel
|
|
1296
|
-
itemHeight: PropTypes.number, // required for vertical carousel
|
|
1297
|
-
sliderWidth: PropTypes.number, // required for horizontal carousel
|
|
1298
|
-
sliderHeight: PropTypes.number, // required for vertical carousel
|
|
1299
|
-
activeAnimationType: PropTypes.string,
|
|
1300
|
-
activeAnimationOptions: PropTypes.object,
|
|
1301
|
-
activeSlideAlignment: PropTypes.oneOf(['center', 'end', 'start']),
|
|
1302
|
-
activeSlideOffset: PropTypes.number,
|
|
1303
|
-
apparitionDelay: PropTypes.number,
|
|
1304
|
-
autoplay: PropTypes.bool,
|
|
1305
|
-
autoplayDelay: PropTypes.number,
|
|
1306
|
-
autoplayInterval: PropTypes.number,
|
|
1307
|
-
callbackOffsetMargin: PropTypes.number,
|
|
1308
|
-
containerCustomStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
1309
|
-
contentContainerCustomStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
1310
|
-
enableMomentum: PropTypes.bool,
|
|
1311
|
-
enableSnap: PropTypes.bool,
|
|
1312
|
-
firstItem: PropTypes.number,
|
|
1313
|
-
hasParallaxImages: PropTypes.bool,
|
|
1314
|
-
inactiveSlideOpacity: PropTypes.number,
|
|
1315
|
-
inactiveSlideScale: PropTypes.number,
|
|
1316
|
-
inactiveSlideShift: PropTypes.number,
|
|
1317
|
-
layout: PropTypes.oneOf(['default', 'stack', 'tinder']),
|
|
1318
|
-
layoutCardOffset: PropTypes.number,
|
|
1319
|
-
lockScrollTimeoutDuration: PropTypes.number,
|
|
1320
|
-
lockScrollWhileSnapping: PropTypes.bool,
|
|
1321
|
-
loop: PropTypes.bool,
|
|
1322
|
-
loopClonesPerSide: PropTypes.number,
|
|
1323
|
-
scrollEnabled: PropTypes.bool,
|
|
1324
|
-
scrollInterpolator: PropTypes.func,
|
|
1325
|
-
slideInterpolatedStyle: PropTypes.func,
|
|
1326
|
-
slideStyle: PropTypes.object,
|
|
1327
|
-
shouldOptimizeUpdates: PropTypes.bool,
|
|
1328
|
-
swipeThreshold: PropTypes.number,
|
|
1329
|
-
useScrollView: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
|
|
1330
|
-
vertical: PropTypes.bool,
|
|
1331
|
-
showsPagination: PropTypes.bool,
|
|
1332
|
-
isCustomScrollWidth: PropTypes.bool,
|
|
1333
|
-
onBeforeSnapToItem: PropTypes.func,
|
|
1334
|
-
onSnapToItem: PropTypes.func,
|
|
1335
|
-
};
|
|
1336
|
-
|
|
1337
|
-
Carousel.defaultProps = {
|
|
1338
|
-
activeAnimationType: 'timing',
|
|
1339
|
-
activeAnimationOptions: null,
|
|
1340
|
-
activeSlideAlignment: 'center',
|
|
1341
|
-
activeSlideOffset: 20,
|
|
1342
|
-
apparitionDelay: 0,
|
|
1343
|
-
autoplay: false,
|
|
1344
|
-
autoplayDelay: 1000,
|
|
1345
|
-
autoplayInterval: 3000,
|
|
1346
|
-
callbackOffsetMargin: 5,
|
|
1347
|
-
containerCustomStyle: {},
|
|
1348
|
-
contentContainerCustomStyle: {},
|
|
1349
|
-
enableMomentum: false,
|
|
1350
|
-
enableSnap: true,
|
|
1351
|
-
firstItem: 0,
|
|
1352
|
-
hasParallaxImages: false,
|
|
1353
|
-
inactiveSlideOpacity: 0.7,
|
|
1354
|
-
inactiveSlideScale: 0.9,
|
|
1355
|
-
inactiveSlideShift: 0,
|
|
1356
|
-
layout: 'default',
|
|
1357
|
-
lockScrollTimeoutDuration: 1000,
|
|
1358
|
-
lockScrollWhileSnapping: false,
|
|
1359
|
-
loop: false,
|
|
1360
|
-
loopClonesPerSide: 3,
|
|
1361
|
-
scrollEnabled: true,
|
|
1362
|
-
slideStyle: {},
|
|
1363
|
-
shouldOptimizeUpdates: true,
|
|
1364
|
-
swipeThreshold: 20,
|
|
1365
|
-
useScrollView: !Animated.FlatList,
|
|
1366
|
-
vertical: false,
|
|
1367
|
-
showsPagination: true,
|
|
1368
|
-
isCustomScrollWidth: false,
|
|
1369
|
-
};
|