UNPKG

@uiw/react-native

Version:
139 lines (126 loc) 3.32 kB
import React, { Component } from 'react'; import { View, Animated, Text, TouchableOpacity, StyleSheet } from 'react-native'; function MaybeTextOrView({ children, ...otherProps }) { if (typeof children === 'string' || children && children.type.displayName === 'Text') { return <Text {...otherProps}>{children}</Text>; } return <View {...otherProps}>{children}</View>; } const styles = StyleSheet.create({ defalut: {}, checkBg: { borderRadius: 999, borderColor: 'rgb(189, 193, 204)', borderWidth: 1, justifyContent: 'center', alignItems: 'center' }, check: { borderRadius: 999, backgroundColor: '#4DD964' }, touch: { flexDirection: 'row', alignItems: 'center' }, label: { marginLeft: 6 } }); export default class Radio extends Component { static defaultProps = { checked: false, circleSize: 20, color: '#c3c5c7', thumbSize: 12 }; constructor(props) { super(props); this.state = { checked: props.checked, sizeValue: new Animated.Value(0), control: 'state' }; } componentDidMount() { this.animatedStart(this.props.checked); } static getDerivedStateFromProps(props, state) { if (state.control === 'state' && props.checked === state.checked) { return { control: 'props' }; } if (props.checked !== state.checked) { Animated.spring(state.sizeValue, { toValue: !!props.checked ? props.thumbSize : 0, overshootClamping: true, useNativeDriver: false }).start(); return { checked: props.checked, control: 'props' }; } return null; } animatedStart(checked) { Animated.spring(this.state.sizeValue, { toValue: !!checked ? this.props.thumbSize : 0, overshootClamping: true, useNativeDriver: false }).start(); } handlePress = event => { const { onPress } = this.props; this.setState({ checked: true, control: 'state' }, () => { this.animatedStart(true); onPress && onPress(event); }); }; render() { const { style, color, circleSize, thumbSize, disabled, ...otherProps } = this.props; const sizeValue = this.state.sizeValue.interpolate({ inputRange: [0, thumbSize], outputRange: [0, thumbSize] // extrapolate: 'clamp', }); const backgroundColor = disabled ? color : '#008EF0'; const borderColor = disabled ? color : '#bdc1cc'; return <View style={[styles.defalut, style]} {...otherProps}> <TouchableOpacity disabled={disabled} style={[styles.touch]} onPress={this.handlePress}> <Animated.View style={[styles.checkBg, { width: circleSize, height: circleSize, borderColor }]}> <Animated.View style={[styles.check, { width: sizeValue, height: sizeValue, backgroundColor }]} /> </Animated.View> {this.props.children && <MaybeTextOrView // eslint-disable-next-line react-native/no-inline-styles style={[styles.label, { opacity: disabled ? 0.3 : 1 }]}> {this.props.children} </MaybeTextOrView>} </TouchableOpacity> </View>; } }