@uiw/react-native
Version:
UIW for React Native
129 lines (128 loc) • 3.35 kB
JavaScript
import React, { useEffect, useState } 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 function Radio(props) {
const [state, setState] = useState({
checked: props.checked,
sizeValue: new Animated.Value(0),
control: 'state'
});
useEffect(() => {
animatedStart(props.checked);
}, []);
useEffect(() => {
if (state.control === 'state' && props.checked === state.checked) {
return setState({
...state,
control: 'props'
});
}
if (props.checked !== state.checked) {
Animated.spring(state.sizeValue, {
toValue: !!props.checked ? props.thumbSize : 0,
overshootClamping: true,
useNativeDriver: false
}).start();
return setState({
...state,
checked: props.checked,
control: 'props'
});
}
}, [props.checked]);
function animatedStart(checked) {
Animated.spring(state.sizeValue, {
toValue: !!checked ? props.thumbSize : 0,
overshootClamping: true,
useNativeDriver: false
}).start();
}
const handlePress = event => {
const {
onPress
} = props;
setState({
...state,
checked: true,
control: 'state'
});
animatedStart(true);
onPress && onPress(event);
};
const {
style,
color,
circleSize,
thumbSize,
disabled,
checkedColor,
borderColor: bdColor,
...otherProps
} = props;
const sizeValue = state.sizeValue.interpolate({
inputRange: [0, thumbSize],
outputRange: [0, thumbSize]
// extrapolate: 'clamp',
});
const backgroundColor = disabled ? color : checkedColor;
const borderColor = disabled ? color : bdColor;
return <View testID="RNE__Radio__wrap" style={[styles.defalut, style]} {...otherProps}>
<TouchableOpacity disabled={disabled} style={[styles.touch]} onPress={handlePress} testID="RNE__Radio__view">
<Animated.View style={[styles.checkBg, {
width: circleSize,
height: circleSize,
borderColor
}]} testID="RNE__Radio__border">
<Animated.View style={[styles.check, {
width: sizeValue,
height: sizeValue,
backgroundColor
}]} testID="RNE__Radio__box" />
</Animated.View>
{props.children && <MaybeTextOrView
// eslint-disable-next-line
style={[styles.label, {
opacity: disabled ? 0.3 : 1
}]}>
{props.children}
</MaybeTextOrView>}
</TouchableOpacity>
</View>;
}
Radio.defaultProps = {
checked: false,
circleSize: 20,
checkedColor: '#008EF0',
borderColor: '#bdc1cc',
color: '#c3c5c7',
thumbSize: 12
};