UNPKG

@nghinv/react-native-switch

Version:
125 lines (120 loc) 3.84 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /** * Created by nghinv on Fri Jun 18 2021 * Copyright (c) 2021 nghinv@lumi.biz */ import React, { useEffect, useCallback } from 'react'; import { StyleSheet } from 'react-native'; import equals from 'react-fast-compare'; import { TapGestureHandler } from 'react-native-gesture-handler'; import Animated, { Extrapolate, interpolate, interpolateColor, useAnimatedGestureHandler, withSpring, withTiming, useAnimatedStyle, useSharedValue, runOnJS } from 'react-native-reanimated'; Switch.defaultProps = { size: 27, thumbColor: 'white', value: false, disabled: false }; const SpringConfigDefault = { mass: 1, damping: 15, stiffness: 120, overshootClamping: false, restSpeedThreshold: 0.001, restDisplacementThreshold: 0.001 }; const DefaultTrackColor = { true: '#31D158', false: 'rgba(120, 120, 120, 0.3)' }; function Switch(props) { var _props$progress; const { value, thumbColor, disabled, onChange, style, ...rest } = props; const size = props.size; const trackColor = { ...DefaultTrackColor, ...props.trackColor }; const trackSize = size + 4; const trackWidth = size * 1.9; const progress = (_props$progress = props.progress) !== null && _props$progress !== void 0 ? _props$progress : useSharedValue(value ? 1 : 0); const thumbWidth = useSharedValue(size); const thumbTransX = useSharedValue(0); useEffect(() => { progress.value = withSpring(value ? 1 : 0, SpringConfigDefault); }, [value]); const onChangeValue = useCallback(() => { onChange && onChange(!value); }, [value]); const onGestureEvent = useAnimatedGestureHandler({ onStart: () => { const newSize = size * 1.2; thumbWidth.value = withTiming(newSize); if (progress.value > 0.5) { thumbTransX.value = withTiming(size - newSize); } }, onFinish: () => { thumbTransX.value = 0; thumbWidth.value = withTiming(size); const newValue = progress.value > 0.5 ? false : true; progress.value = withSpring(newValue ? 0 : 1, SpringConfigDefault); runOnJS(onChangeValue)(); } }); const trackStyle = useAnimatedStyle(() => { return { backgroundColor: interpolateColor(progress.value, [0, 1], [trackColor.false, trackColor.true]) }; }); const thumbStyle = useAnimatedStyle(() => { return { width: thumbWidth.value, transform: [{ translateX: interpolate(progress.value, [0, 1], [0, trackWidth - size - 4], Extrapolate.CLAMP) }, { translateX: thumbTransX.value }] }; }); return /*#__PURE__*/React.createElement(TapGestureHandler, { enabled: !disabled && !!onChange, onGestureEvent: onGestureEvent }, /*#__PURE__*/React.createElement(Animated.View, _extends({}, rest, { style: [{ width: trackWidth, height: trackSize, borderRadius: trackSize / 2, opacity: disabled ? 0.5 : 1, justifyContent: 'center' }, trackStyle, style] }), /*#__PURE__*/React.createElement(Animated.View, { pointerEvents: "box-none", style: [styles.thumb, { height: size, borderRadius: size / 2, backgroundColor: thumbColor }, thumbStyle] }))); } const styles = StyleSheet.create({ thumb: { position: 'absolute', left: 2, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5 } }); export default /*#__PURE__*/React.memo(Switch, equals); //# sourceMappingURL=index.js.map