diff --git a/.eslintrc b/.eslintrc index d4739ac63..8622ce811 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,8 +1,9 @@ { - "parser" : "babel-eslint", + "parser" : "@babel/eslint-parser", "extends" : [ "standard", - "standard-react" + "standard-react", + "plugin:react/recommended" ], "plugins": [ "react" @@ -15,9 +16,15 @@ "__DEV__": false }, "parserOptions": { + "requireConfigFile": false, "ecmaVersion": 6, "ecmaFeatures": { "jsx": true + }, + "babelOptions": { + "parserOpts": { + "plugins": ["jsx"] + } } }, "rules": { diff --git a/CHANGELOG.md b/CHANGELOG.md index f43915ec6..449e36c9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v3.9.2 + +* Update package dependencies to eliminate vulnerability warnings +* Fix error due to deprecated ViewPropTypes usage +* Add lint script & fix existing linting errors + ## v3.9.1 * Fix for `getNode()` deprecation warning with RN `0.62+` (thanks [@r0b0t3d](https://github.com/r0b0t3d)) diff --git a/example/__tests__/index.js b/example/__tests__/index.js index c433b04e5..d7227b183 100644 --- a/example/__tests__/index.js +++ b/example/__tests__/index.js @@ -9,6 +9,7 @@ import Root from '../src/index'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; +// eslint-disable-next-line no-undef it('renders correctly', () => { - renderer.create(); + renderer.create(); }); diff --git a/example/babel.config.js b/example/babel.config.js index f842b77fc..c50a8a001 100644 --- a/example/babel.config.js +++ b/example/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - presets: ['module:metro-react-native-babel-preset'], + presets: ['module:metro-react-native-babel-preset'] }; diff --git a/example/index.js b/example/index.js index 9ee81b922..785d34342 100644 --- a/example/index.js +++ b/example/index.js @@ -2,8 +2,8 @@ * @format */ -import {AppRegistry} from 'react-native'; +import { AppRegistry } from 'react-native'; import App from './src'; -import {name as appName} from './app.json'; +import { name as appName } from './app.json'; AppRegistry.registerComponent(appName, () => App); diff --git a/example/metro.config.js b/example/metro.config.js index 13a964217..95c89fedd 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -6,12 +6,12 @@ */ module.exports = { - transformer: { - getTransformOptions: async () => ({ - transform: { - experimentalImportSupport: false, - inlineRequires: false, - }, - }), - }, + transformer: { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: false + } + }) + } }; diff --git a/example/src/components/SliderEntry.js b/example/src/components/SliderEntry.js index 19ad3bfff..6624a6c9c 100644 --- a/example/src/components/SliderEntry.js +++ b/example/src/components/SliderEntry.js @@ -16,42 +16,46 @@ export default class SliderEntry extends Component { get image () { const { data: { illustration }, parallax, parallaxProps, even } = this.props; - return parallax ? ( - - ) : ( - - ); + return parallax ? + ( + + ) : + ( + + ); } render () { const { data: { title, subtitle }, even } = this.props; - const uppercaseTitle = title ? ( - - { title.toUpperCase() } - - ) : false; + const uppercaseTitle = title ? + ( + + { title.toUpperCase() } + + ) : + false; return ( { alert(`You've clicked '${title}'`); }} - > + > { this.image } diff --git a/example/src/index.js b/example/src/index.js index 17da26ee9..c47253908 100644 --- a/example/src/index.js +++ b/example/src/index.js @@ -20,11 +20,11 @@ export default class example extends Component { }; } - _renderItem ({item, index}) { + _renderItem ({ item, index }) { return ; } - _renderItemWithParallax ({item, index}, parallaxProps) { + _renderItemWithParallax ({ item, index }, parallaxProps) { return ( ; } - _renderDarkItem ({item, index}) { + _renderDarkItem ({ item, index }) { return ; } @@ -51,7 +51,7 @@ export default class example extends Component { {`Example ${number}`} {title} this._slider1Ref = c} + ref={c => { this._slider1Ref = c; }} data={ENTRIES1} renderItem={this._renderItemWithParallax} sliderWidth={sliderWidth} @@ -136,23 +136,25 @@ export default class example extends Component { const isEven = refNumber % 2 === 0; // Do not render examples on Android; because of the zIndex bug, they won't work as is - return !IS_ANDROID ? ( - - {`Example ${number}`} - {title} - - - ) : false; + return !IS_ANDROID ? + ( + + {`Example ${number}`} + {title} + + + ) : + false; } get gradient () { diff --git a/package.json b/package.json index 7304e37ce..9124d2aeb 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,15 @@ { "name": "react-native-snap-carousel", - "version": "3.9.1", + "version": "3.9.2", "description": "Swiper/carousel component for React Native with previews, multiple layouts, parallax images, performant handling of huge numbers of items, and RTL support. Compatible with Android & iOS.", "main": "src/index.js", "repository": { "type": "git", "url": "github.com/meliorence/react-native-snap-carousel" }, + "scripts": { + "lint": "eslint ." + }, "keywords": [ "react", "native", @@ -37,23 +40,24 @@ "author": "Meliorence (github.com/meliorence)", "license": "BSD-3-Clause", "dependencies": { + "deprecated-react-native-prop-types": "^5.0.0", "prop-types": "^15.6.1", - "react-addons-shallow-compare": "15.6.2" + "react-addons-shallow-compare": "^15.6.3" }, "peerDependencies": { "react": ">=15.0.0", "react-native": "*" }, "devDependencies": { - "babel-eslint": "^8.2.2", - "eslint": "^4.19.1", - "eslint-config-standard": "^10.2.1", - "eslint-config-standard-react": "^5.0.0", - "eslint-plugin-import": "^2.11.0", - "eslint-plugin-node": "^5.2.1", - "eslint-plugin-promise": "^3.7.0", - "eslint-plugin-react": "^7.7.0", - "eslint-plugin-standard": "^3.0.1" + "@babel/eslint-parser": "^7.24.7", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-config-standard-react": "^13.0.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^6.2.0", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-standard": "^5.0.0" }, "homepage": "https://github.com/meliorence/react-native-snap-carousel", "bugs": { diff --git a/src/carousel/Carousel.js b/src/carousel/Carousel.js index dae71a3da..585852b8c 100644 --- a/src/carousel/Carousel.js +++ b/src/carousel/Carousel.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; -import { Animated, Easing, FlatList, I18nManager, Platform, ScrollView, View, ViewPropTypes } from 'react-native'; +import { Animated, Easing, FlatList, I18nManager, Platform, ScrollView, View } from 'react-native'; +import { ViewPropTypes } from 'deprecated-react-native-prop-types'; import PropTypes from 'prop-types'; import shallowCompare from 'react-addons-shallow-compare'; import { @@ -28,8 +29,10 @@ const IS_RTL = I18nManager.isRTL; export default class Carousel extends Component { static propTypes = { + style: PropTypes.object, data: PropTypes.array.isRequired, renderItem: PropTypes.func.isRequired, + keyExtractor: PropTypes.func, itemWidth: PropTypes.number, // required for horizontal carousel itemHeight: PropTypes.number, // required for vertical carousel sliderWidth: PropTypes.number, // required for horizontal carousel @@ -62,6 +65,16 @@ export default class Carousel extends Component { scrollInterpolator: PropTypes.func, slideInterpolatedStyle: PropTypes.func, slideStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, + onLayout: PropTypes.func, + onScroll: PropTypes.func, + onScrollBeginDrag: PropTypes.func, + onScrollEnd: PropTypes.func, + onScrollEndDrag: PropTypes.func, + onMomentumScrollEnd: PropTypes.func, + onTouchStart: PropTypes.func, + onTouchEnd: PropTypes.func, + onTouchRelease: PropTypes.func, + onStartShouldSetResponderCapture: PropTypes.func, shouldOptimizeUpdates: PropTypes.bool, swipeThreshold: PropTypes.number, useScrollView: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]), @@ -100,7 +113,7 @@ export default class Carousel extends Component { swipeThreshold: 20, useScrollView: !AnimatedFlatList, vertical: false - } + }; constructor (props) { super(props); @@ -151,6 +164,7 @@ export default class Carousel extends Component { this._ignoreNextMomentum = false; // Warnings + /* eslint-disable react/prop-types */ if (!ViewPropTypes) { console.warn('react-native-snap-carousel: It is recommended to use at least version 0.44 of React Native with the plugin'); } @@ -169,6 +183,7 @@ export default class Carousel extends Component { if (props.onScrollViewScroll) { console.error('react-native-snap-carousel: Prop `onScrollViewScroll` has been removed. Use `onScroll` instead'); } + /* eslint-enable */ } componentDidMount () { @@ -263,7 +278,7 @@ export default class Carousel extends Component { } if (this.props.onScroll !== prevProps.onScroll) { - this._setScrollHandler(this.props); + this._setScrollHandler(this.props); } } @@ -291,34 +306,34 @@ export default class Carousel extends Component { return this._currentContentOffset; } - _setScrollHandler(props) { - // Native driver for scroll events - const scrollEventConfig = { - listener: this._onScroll, - useNativeDriver: true, - }; - this._scrollPos = new Animated.Value(0); - const argMapping = props.vertical - ? [{ nativeEvent: { contentOffset: { y: this._scrollPos } } }] - : [{ nativeEvent: { contentOffset: { x: this._scrollPos } } }]; + _setScrollHandler (props) { + // Native driver for scroll events + const scrollEventConfig = { + listener: this._onScroll, + useNativeDriver: true + }; + this._scrollPos = new Animated.Value(0); + const argMapping = props.vertical ? + [{ nativeEvent: { contentOffset: { y: this._scrollPos } } }] : + [{ nativeEvent: { contentOffset: { x: this._scrollPos } } }]; - if (props.onScroll && Array.isArray(props.onScroll._argMapping)) { + if (props.onScroll && Array.isArray(props.onScroll._argMapping)) { // Because of a react-native issue https://github.com/facebook/react-native/issues/13294 - argMapping.pop(); - const [ argMap ] = props.onScroll._argMapping; - if (argMap && argMap.nativeEvent && argMap.nativeEvent.contentOffset) { - // Shares the same animated value passed in props - this._scrollPos = + argMapping.pop(); + const [argMap] = props.onScroll._argMapping; + if (argMap && argMap.nativeEvent && argMap.nativeEvent.contentOffset) { + // Shares the same animated value passed in props + this._scrollPos = argMap.nativeEvent.contentOffset.x || argMap.nativeEvent.contentOffset.y || this._scrollPos; + } + argMapping.push(...props.onScroll._argMapping); } - argMapping.push(...props.onScroll._argMapping); - } - this._onScrollHandler = Animated.event( - argMapping, - scrollEventConfig - ); + this._onScrollHandler = Animated.event( + argMapping, + scrollEventConfig + ); } _needsScrollView () { @@ -438,6 +453,7 @@ export default class Carousel extends Component { (index - loopClonesPerSide) % dataLength : index - dataLength - loopClonesPerSide; } else if (index < loopClonesPerSide) { + // eslint-disable-next-line no-warning-comments // TODO: is there a simpler way of determining the interpolated index? if (loopClonesPerSide > dataLength) { const baseDataIndexes = []; @@ -579,7 +595,7 @@ export default class Carousel extends Component { return; } - let interpolators = []; + const interpolators = []; this._positions = []; this._getCustomData(props).forEach((itemData, index) => { @@ -636,11 +652,11 @@ export default class Carousel extends Component { isInteraction: false, useNativeDriver: true, ...activeAnimationOptions, - toValue: toValue + toValue }; return Animated.parallel([ - Animated['timing']( + Animated.timing( animatedValue, { ...animationCommonOptions, easing: Easing.linear } ), @@ -658,7 +674,7 @@ export default class Carousel extends Component { const _currentDataIndex = this._getDataIndex(_currentIndex); const _nextIndex = this._getCustomIndex(next); const _nextDataIndex = this._getDataIndex(_nextIndex); - let animations = []; + const animations = []; // Keep animations in sync when looping if (this._enableLoop()) { @@ -747,12 +763,14 @@ export default class Carousel extends Component { return; } - const specificOptions = this._needsScrollView() ? { - x: vertical ? 0 : offset, - y: vertical ? offset : 0 - } : { - offset - }; + const specificOptions = this._needsScrollView() ? + { + x: vertical ? 0 : offset, + y: vertical ? offset : 0 + } : + { + offset + }; const options = { ...specificOptions, animated @@ -822,7 +840,7 @@ export default class Carousel extends Component { this._repositionScroll(nextActiveItem); } - if (typeof onScroll === "function" && event) { + if (typeof onScroll === 'function' && event) { onScroll(event); } } @@ -838,7 +856,7 @@ export default class Carousel extends Component { } _onTouchStart () { - const { onTouchStart } = this.props + const { onTouchStart } = this.props; // `onTouchStart` is fired even when `scrollEnabled` is set to `false` if (this._getScrollEnabled() !== false && this._autoplaying) { @@ -846,12 +864,12 @@ export default class Carousel extends Component { } if (onTouchStart) { - onTouchStart() + onTouchStart(); } } _onTouchEnd () { - const { onTouchEnd } = this.props + const { onTouchEnd } = this.props; if (this._getScrollEnabled() !== false && this._autoplay && !this._autoplaying) { // This event is buggy on Android, so a fallback is provided in _onScrollEnd() @@ -859,7 +877,7 @@ export default class Carousel extends Component { } if (onTouchEnd) { - onTouchEnd() + onTouchEnd(); } } @@ -1218,20 +1236,24 @@ export default class Carousel extends Component { const Component = animate ? Animated.View : View; const animatedStyle = animate ? this._getSlideInterpolatedStyle(index, animatedValue) : {}; - const parallaxProps = hasParallaxImages ? { - scrollPosition: this._scrollPos, - carouselRef: this._carouselRef, - vertical, - sliderWidth, - sliderHeight, - itemWidth, - itemHeight - } : undefined; + const parallaxProps = hasParallaxImages ? + { + scrollPosition: this._scrollPos, + carouselRef: this._carouselRef, + vertical, + sliderWidth, + sliderHeight, + itemWidth, + itemHeight + } : + undefined; const mainDimension = vertical ? { height: itemHeight } : { width: itemWidth }; - const specificProps = this._needsScrollView() ? { - key: keyExtractor ? keyExtractor(item, index) : this._getKeyExtractor(item, index) - } : {}; + const specificProps = this._needsScrollView() ? + { + key: keyExtractor ? keyExtractor(item, index) : this._getKeyExtractor(item, index) + } : + {}; return ( @@ -1259,12 +1281,14 @@ export default class Carousel extends Component { const maxToRenderPerBatch = 1 + (initialNumToRender * 2); const windowSize = maxToRenderPerBatch; - const specificProps = !this._needsScrollView() ? { - initialNumToRender: initialNumToRender, - maxToRenderPerBatch: maxToRenderPerBatch, - windowSize: windowSize + const specificProps = !this._needsScrollView() ? + { + initialNumToRender, + maxToRenderPerBatch, + windowSize // updateCellsBatchingPeriod - } : {}; + } : + {}; return { decelerationRate: enableMomentum ? 0.9 : 'fast', @@ -1304,28 +1328,31 @@ export default class Carousel extends Component { { width: sliderWidth, flexDirection: this._needsRTLAdaptations() ? 'row-reverse' : 'row' } ]; const contentContainerStyle = [ - vertical ? { - paddingTop: this._getContainerInnerMargin(), - paddingBottom: this._getContainerInnerMargin(true) - } : { - paddingLeft: this._getContainerInnerMargin(), - paddingRight: this._getContainerInnerMargin(true) - }, + vertical ? + { + paddingTop: this._getContainerInnerMargin(), + paddingBottom: this._getContainerInnerMargin(true) + } : + { + paddingLeft: this._getContainerInnerMargin(), + paddingRight: this._getContainerInnerMargin(true) + }, contentContainerCustomStyle || {} ]; - const specificProps = !this._needsScrollView() ? { - // extraData: this.state, - renderItem: this._renderItem, - numColumns: 1, - keyExtractor: keyExtractor || this._getKeyExtractor - } : {}; + const specificProps = !this._needsScrollView() ? + { + renderItem: this._renderItem, + numColumns: 1, + keyExtractor: keyExtractor || this._getKeyExtractor + } : + {}; return { - ref: c => this._carouselRef = c, + ref: c => { this._carouselRef = c; }, data: this._getCustomData(), style: containerStyle, - contentContainerStyle: contentContainerStyle, + contentContainerStyle, horizontal: !vertical, scrollEventThrottle: 1, onScroll: this._onScrollHandler, @@ -1354,18 +1381,20 @@ export default class Carousel extends Component { ...this._getComponentStaticProps() }; - const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView : AnimatedScrollView + const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView : AnimatedScrollView; - return this._needsScrollView() ? ( - - { - this._getCustomData().map((item, index) => { - return this._renderItem({ item, index }); - }) - } - - ) : ( - - ); + return this._needsScrollView() ? + ( + + { + this._getCustomData().map((item, index) => { + return this._renderItem({ item, index }); + }) + } + + ) : + ( + + ); } } diff --git a/src/pagination/Pagination.js b/src/pagination/Pagination.js index 5c021cf36..f5ff3f7e8 100644 --- a/src/pagination/Pagination.js +++ b/src/pagination/Pagination.js @@ -1,5 +1,6 @@ import React, { PureComponent } from 'react'; -import { I18nManager, Platform, View, ViewPropTypes } from 'react-native'; +import { I18nManager, Platform, View } from 'react-native'; +import { ViewPropTypes } from 'deprecated-react-native-prop-types'; import PropTypes from 'prop-types'; import PaginationDot from './PaginationDot'; import styles from './Pagination.style'; @@ -31,7 +32,7 @@ export default class Pagination extends PureComponent { animatedDuration: PropTypes.number, animatedFriction: PropTypes.number, animatedTension: PropTypes.number, - delayPressInDot: PropTypes.number, + delayPressInDot: PropTypes.number }; static defaultProps = { @@ -42,8 +43,8 @@ export default class Pagination extends PureComponent { animatedDuration: 250, animatedFriction: 4, animatedTension: 50, - delayPressInDot: 0, - } + delayPressInDot: 0 + }; constructor (props) { super(props); @@ -98,7 +99,7 @@ export default class Pagination extends PureComponent { animatedDuration, animatedFriction, animatedTension, - delayPressInDot, + delayPressInDot } = this.props; if (renderDots) { @@ -146,9 +147,10 @@ export default class Pagination extends PureComponent { const style = [ styles.sliderPagination, - { flexDirection: vertical ? - 'column' : - (this._needsRTLAdaptations() ? 'row-reverse' : 'row') + { + flexDirection: vertical ? + 'column' : + (this._needsRTLAdaptations() ? 'row-reverse' : 'row') }, containerStyle || {} ]; diff --git a/src/pagination/PaginationDot.js b/src/pagination/PaginationDot.js index e59d1969f..6a6223fad 100644 --- a/src/pagination/PaginationDot.js +++ b/src/pagination/PaginationDot.js @@ -1,5 +1,6 @@ import React, { PureComponent } from 'react'; -import { View, Animated, Easing, TouchableOpacity, ViewPropTypes } from 'react-native'; +import { View, Animated, Easing, TouchableOpacity } from 'react-native'; +import { ViewPropTypes } from 'deprecated-react-native-prop-types'; import PropTypes from 'prop-types'; import styles from './Pagination.style'; @@ -17,7 +18,11 @@ export default class PaginationDot extends PureComponent { inactiveStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, index: PropTypes.number, style: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, - tappable: PropTypes.bool + tappable: PropTypes.bool, + animatedDuration: PropTypes.number, + animatedFriction: PropTypes.number, + animatedTension: PropTypes.number, + delayPressInDot: PropTypes.number }; constructor (props) { @@ -43,7 +48,7 @@ export default class PaginationDot extends PureComponent { _animate (toValue = 0) { const { animColor, animOpacity, animTransform } = this.state; - const { animatedDuration, animatedFriction, animatedTension } = this.props + const { animatedDuration, animatedFriction, animatedTension } = this.props; const commonProperties = { toValue, @@ -52,7 +57,7 @@ export default class PaginationDot extends PureComponent { useNativeDriver: !this._shouldAnimateColor }; - let animations = [ + const animations = [ Animated.timing(animOpacity, { easing: Easing.linear, ...commonProperties @@ -109,12 +114,14 @@ export default class PaginationDot extends PureComponent { }) }] }; - const animatedColor = this._shouldAnimateColor ? { - backgroundColor: animColor.interpolate({ - inputRange: [0, 1], - outputRange: [inactiveColor, color] - }) - } : {}; + const animatedColor = this._shouldAnimateColor ? + { + backgroundColor: animColor.interpolate({ + inputRange: [0, 1], + outputRange: [inactiveColor, color] + }) + } : + {}; const dotContainerStyle = [ styles.sliderPaginationDotContainer, @@ -129,17 +136,19 @@ export default class PaginationDot extends PureComponent { animatedColor ]; - const onPress = tappable ? () => { - try { - const currentRef = carouselRef.current || carouselRef; - currentRef._snapToItem(currentRef._getPositionIndex(index)); - } catch (error) { - console.warn( - 'react-native-snap-carousel | Pagination: ' + + const onPress = tappable ? + () => { + try { + const currentRef = carouselRef.current || carouselRef; + currentRef._snapToItem(currentRef._getPositionIndex(index)); + } catch (error) { + console.warn( + 'react-native-snap-carousel | Pagination: ' + '`carouselRef` has to be a Carousel ref.\n' + error - ); - } - } : undefined; + ); + } + } : + undefined; return ( - - - ) : false; + return status === 1 && showSpinner ? + ( + + + + ) : + false; } render () { diff --git a/src/utils/animations.js b/src/utils/animations.js index bdb58b62d..8a11a3633 100644 --- a/src/utils/animations.js +++ b/src/utils/animations.js @@ -14,7 +14,7 @@ const IS_ANDROID = Platform.OS === 'android'; // ] export function getInputRangeFromIndexes (range, index, carouselProps) { const sizeRef = carouselProps.vertical ? carouselProps.itemHeight : carouselProps.itemWidth; - let inputRange = []; + const inputRange = []; for (let i = 0; i < range.length; i++) { inputRange.push((index - range[i]) * sizeRef); @@ -144,59 +144,61 @@ export function stackAnimatedStyles (index, animatedValue, carouselProps, cardOf const opacityOutputRange = carouselProps.inactiveSlideOpacity === 1 ? [1, 1, 1, 0] : [1, 0.75, 0.5, 0]; - return IS_ANDROID ? { + return IS_ANDROID ? + { // elevation: carouselProps.data.length - index, // fix zIndex bug visually, but not from a logic point of view - opacity: animatedValue.interpolate({ - inputRange: [-3, -2, -1, 0], - outputRange: opacityOutputRange.reverse(), - extrapolate: 'clamp' - }), - transform: [{ - scale: animatedValue.interpolate({ - inputRange: [-2, -1, 0, 1], - outputRange: [card2Scale, card1Scale, 1, card1Scale], - extrapolate: 'clamp' - }) - }, { - [translateProp]: animatedValue.interpolate({ - inputRange: [-3, -2, -1, 0, 1], - outputRange: [ - getTranslateFromScale(-3, card2Scale), - getTranslateFromScale(-2, card2Scale), - getTranslateFromScale(-1, card1Scale), - 0, - sizeRef * 0.5 - ], - extrapolate: 'clamp' - }) - }] - } : { - zIndex: carouselProps.data.length - index, - opacity: animatedValue.interpolate({ - inputRange: [0, 1, 2, 3], - outputRange: opacityOutputRange, - extrapolate: 'clamp' - }), - transform: [{ - scale: animatedValue.interpolate({ - inputRange: [-1, 0, 1, 2], - outputRange: [card1Scale, 1, card1Scale, card2Scale], + opacity: animatedValue.interpolate({ + inputRange: [-3, -2, -1, 0], + outputRange: opacityOutputRange.reverse(), extrapolate: 'clamp' - }) - }, { - [translateProp]: animatedValue.interpolate({ - inputRange: [-1, 0, 1, 2, 3], - outputRange: [ - -sizeRef * 0.5, - 0, - getTranslateFromScale(1, card1Scale), - getTranslateFromScale(2, card2Scale), - getTranslateFromScale(3, card2Scale) - ], + }), + transform: [{ + scale: animatedValue.interpolate({ + inputRange: [-2, -1, 0, 1], + outputRange: [card2Scale, card1Scale, 1, card1Scale], + extrapolate: 'clamp' + }) + }, { + [translateProp]: animatedValue.interpolate({ + inputRange: [-3, -2, -1, 0, 1], + outputRange: [ + getTranslateFromScale(-3, card2Scale), + getTranslateFromScale(-2, card2Scale), + getTranslateFromScale(-1, card1Scale), + 0, + sizeRef * 0.5 + ], + extrapolate: 'clamp' + }) + }] + } : + { + zIndex: carouselProps.data.length - index, + opacity: animatedValue.interpolate({ + inputRange: [0, 1, 2, 3], + outputRange: opacityOutputRange, extrapolate: 'clamp' - }) - }] - }; + }), + transform: [{ + scale: animatedValue.interpolate({ + inputRange: [-1, 0, 1, 2], + outputRange: [card1Scale, 1, card1Scale, card2Scale], + extrapolate: 'clamp' + }) + }, { + [translateProp]: animatedValue.interpolate({ + inputRange: [-1, 0, 1, 2, 3], + outputRange: [ + -sizeRef * 0.5, + 0, + getTranslateFromScale(1, card1Scale), + getTranslateFromScale(2, card2Scale), + getTranslateFromScale(3, card2Scale) + ], + extrapolate: 'clamp' + }) + }] + }; } // Tinder animation @@ -235,91 +237,93 @@ export function tinderAnimatedStyles (index, animatedValue, carouselProps, cardO return Math.round(cardOffset * Math.abs(cardIndex) / scale); }; - return IS_ANDROID ? { - // elevation: carouselProps.data.length - index, // fix zIndex bug visually, but not from a logic point of view - opacity: animatedValue.interpolate({ - inputRange: [-3, -2, -1, 0, 1], - outputRange: [0, peekingCardsOpacity, peekingCardsOpacity, 1, 0], - extrapolate: 'clamp' - }), - transform: [{ - scale: animatedValue.interpolate({ - inputRange: [-3, -2, -1, 0], - outputRange: [card3Scale, card2Scale, card1Scale, 1], - extrapolate: 'clamp' - }) - }, { - rotate: animatedValue.interpolate({ - inputRange: [0, 1], - outputRange: ['0deg', '22deg'], - extrapolate: 'clamp' - }) - }, { - [mainTranslateProp]: animatedValue.interpolate({ + return IS_ANDROID ? + { + // elevation: carouselProps.data.length - index, // fix zIndex bug visually, but not from a logic point of view + opacity: animatedValue.interpolate({ inputRange: [-3, -2, -1, 0, 1], - outputRange: [ - getMainTranslateFromScale(-3, card3Scale), - getMainTranslateFromScale(-2, card2Scale), - getMainTranslateFromScale(-1, card1Scale), - 0, - sizeRef * 1.1 - ], - extrapolate: 'clamp' - }) - }, { - [secondaryTranslateProp]: animatedValue.interpolate({ - inputRange: [-3, -2, -1, 0], - outputRange: [ - getSecondaryTranslateFromScale(-3, card3Scale), - getSecondaryTranslateFromScale(-2, card2Scale), - getSecondaryTranslateFromScale(-1, card1Scale), - 0 - ], - extrapolate: 'clamp' - }) - }] - } : { - zIndex: carouselProps.data.length - index, - opacity: animatedValue.interpolate({ - inputRange: [-1, 0, 1, 2, 3], - outputRange: [0, 1, peekingCardsOpacity, peekingCardsOpacity, 0], - extrapolate: 'clamp' - }), - transform: [{ - scale: animatedValue.interpolate({ - inputRange: [0, 1, 2, 3], - outputRange: [1, card1Scale, card2Scale, card3Scale], + outputRange: [0, peekingCardsOpacity, peekingCardsOpacity, 1, 0], extrapolate: 'clamp' - }) - }, { - rotate: animatedValue.interpolate({ - inputRange: [-1, 0], - outputRange: ['-22deg', '0deg'], - extrapolate: 'clamp' - }) - }, { - [mainTranslateProp]: animatedValue.interpolate({ + }), + transform: [{ + scale: animatedValue.interpolate({ + inputRange: [-3, -2, -1, 0], + outputRange: [card3Scale, card2Scale, card1Scale, 1], + extrapolate: 'clamp' + }) + }, { + rotate: animatedValue.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '22deg'], + extrapolate: 'clamp' + }) + }, { + [mainTranslateProp]: animatedValue.interpolate({ + inputRange: [-3, -2, -1, 0, 1], + outputRange: [ + getMainTranslateFromScale(-3, card3Scale), + getMainTranslateFromScale(-2, card2Scale), + getMainTranslateFromScale(-1, card1Scale), + 0, + sizeRef * 1.1 + ], + extrapolate: 'clamp' + }) + }, { + [secondaryTranslateProp]: animatedValue.interpolate({ + inputRange: [-3, -2, -1, 0], + outputRange: [ + getSecondaryTranslateFromScale(-3, card3Scale), + getSecondaryTranslateFromScale(-2, card2Scale), + getSecondaryTranslateFromScale(-1, card1Scale), + 0 + ], + extrapolate: 'clamp' + }) + }] + } : + { + zIndex: carouselProps.data.length - index, + opacity: animatedValue.interpolate({ inputRange: [-1, 0, 1, 2, 3], - outputRange: [ - -sizeRef * 1.1, - 0, - getMainTranslateFromScale(1, card1Scale), - getMainTranslateFromScale(2, card2Scale), - getMainTranslateFromScale(3, card3Scale) - ], + outputRange: [0, 1, peekingCardsOpacity, peekingCardsOpacity, 0], extrapolate: 'clamp' - }) - }, { - [secondaryTranslateProp]: animatedValue.interpolate({ - inputRange: [0, 1, 2, 3], - outputRange: [ - 0, - getSecondaryTranslateFromScale(1, card1Scale), - getSecondaryTranslateFromScale(2, card2Scale), - getSecondaryTranslateFromScale(3, card3Scale) - ], - extrapolate: 'clamp' - }) - }] - }; + }), + transform: [{ + scale: animatedValue.interpolate({ + inputRange: [0, 1, 2, 3], + outputRange: [1, card1Scale, card2Scale, card3Scale], + extrapolate: 'clamp' + }) + }, { + rotate: animatedValue.interpolate({ + inputRange: [-1, 0], + outputRange: ['-22deg', '0deg'], + extrapolate: 'clamp' + }) + }, { + [mainTranslateProp]: animatedValue.interpolate({ + inputRange: [-1, 0, 1, 2, 3], + outputRange: [ + -sizeRef * 1.1, + 0, + getMainTranslateFromScale(1, card1Scale), + getMainTranslateFromScale(2, card2Scale), + getMainTranslateFromScale(3, card3Scale) + ], + extrapolate: 'clamp' + }) + }, { + [secondaryTranslateProp]: animatedValue.interpolate({ + inputRange: [0, 1, 2, 3], + outputRange: [ + 0, + getSecondaryTranslateFromScale(1, card1Scale), + getSecondaryTranslateFromScale(2, card2Scale), + getSecondaryTranslateFromScale(3, card3Scale) + ], + extrapolate: 'clamp' + }) + }] + }; }