@uiw/react-native
Version:
UIW for React Native
136 lines (125 loc) • 3.26 kB
JavaScript
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)
};
}
componentDidMount() {
// this.setState({
// checked: this.props.checked,
// });
this.animatedStart(this.props.checked);
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.checked !== this.props.checked) {
this.setState({
checked: nextProps.checked
}, () => {
this.animatedStart(nextProps.checked);
});
}
}
animatedStart(checked) {
if (checked) {
Animated.spring(this.state.sizeValue, {
toValue: this.props.thumbSize,
overshootClamping: true,
useNativeDriver: false
}).start();
} else {
Animated.spring(this.state.sizeValue, {
toValue: 0,
overshootClamping: true,
useNativeDriver: false
}).start();
}
}
handlePress = event => {
const {
onPress
} = this.props;
this.setState({
checked: true
}, () => {
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>;
}
}