From 76720729c804d3e5518a7adba5bfbd7b27cb029c Mon Sep 17 00:00:00 2001 From: Siamak Date: Sun, 6 Oct 2019 18:21:14 +0800 Subject: [PATCH] main component added --- RadioButtonRN.js | 276 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 35 ++++++ 2 files changed, 311 insertions(+) create mode 100644 RadioButtonRN.js create mode 100644 package.json diff --git a/RadioButtonRN.js b/RadioButtonRN.js new file mode 100644 index 0000000..54a9409 --- /dev/null +++ b/RadioButtonRN.js @@ -0,0 +1,276 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { StyleSheet, View, Text, Animated, TouchableOpacity } from 'react-native'; + + +class RadioButtonRN extends React.Component { + + constructor(props) { + super(props); + + this.state = { + activeIndex: -1, + fadeAnim: new Animated.Value(0), + animations: [] + }; + // this.fadeAnim = new Animated.Value(0); + + this.animations = [ + { + name: 'zoomIn', + animation: { + scale: this.state.fadeAnim.interpolate({ + inputRange: [0, 1], + outputRange: [0, 1] + }) + } + }, + { + name: 'pulse', + animation: { + scale: this.state.fadeAnim.interpolate({ + inputRange: [0, 0.4, 0.7, 1], + outputRange: [0.7, 1, 1.3, 1] + }) + } + }, + { + name: 'shake', + animation: { + scale: this.state.fadeAnim.interpolate({ + inputRange: [0, 0.2, 0.4, 0.6, 0.8, 1], + outputRange: [0.8, 1.2, 0.8, 1.2, 0.8, 1] + }) + } + }, + { + name: 'rotate', + animation: { + rotate: this.state.fadeAnim.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '360deg'] + }) + } + }, + ] + + this._changeRadio = this._changeRadio.bind(this); + this._checkAnimatons = this._checkAnimatons.bind(this); + } + + componentDidMount() { + this._checkAnimatons(); + } + + componentDidUpdate(prevProps, prevState) { + if (this.state.activeIndex === -1 && this.props.initial > 0) { + const initialActive = this.props.initial - 1; + this._changeRadio(this.props.data[initialActive], initialActive); + } + if (this.props.initial !== prevProps.initial) { + const initialActive = this.props.initial - 1; + this._changeRadio(this.props.data[initialActive], initialActive); + } + if (this.props.animationTypes !== prevProps.animationTypes) { + this._checkAnimatons(); + } + } + + _checkAnimatons() { + const { animationTypes } = this.props; + + this.setState({ animations: [] }); + const newAnim = []; + animationTypes && animationTypes.map((item, index) => { + const itm = this.animations.find((e) => e.name === item); + if (itm) { + newAnim.push(itm.animation); + } + }) + this.setState({ animations: newAnim }); + } + + _changeRadio(item, activeIndex) { + this.setState({ activeIndex }); + if (activeIndex !== this.state.activeIndex) { + this.fadeInAnimation(); + } + this.props.selectedBtn(item); + } + + fadeInAnimation = () => { + // this.fadeAnim.setValue(0) + Animated.timing(this.state.fadeAnim, { + toValue: 0, + duration: 0, + useNativeDriver: true, + }).start(() => { + Animated.timing(this.state.fadeAnim, { + toValue: 1, + duration: this.props.duration, + delay: 10, + useNativeDriver: true, + }).start(); + }); + } + + render() { + let { activeIndex, fadeAnim, animations } = this.state; + let { boxStyle, style, circleSize, textStyle, data, icon, activeColor, deactiveColor, boxActiveBgColor, boxDeactiveBgColor, box, textColor } = this.props; + + return ( + + { + data.map((item, index) => { + return ( + this._changeRadio(item, index)} + > + + + + + { + icon ? + icon + : + + } + + + + + + + + {item.label} + + + + ) + }) + } + + ); + } + +} + +/* Styles ====================================== */ +const styles = StyleSheet.create({ + productBox: { + flexDirection: 'row', + borderRadius: 7, + borderWidth: 1, + paddingHorizontal: 10, + paddingVertical: 15, + marginTop: 10 + }, + productBoxLess: { + flexDirection: 'row', + marginTop: 10 + }, + leftProductBox: { + flex: 1, + alignItems: 'center', + justifyContent: 'center' + }, + centerProductBox: { + flex: 6, + justifyContent: 'center', + alignItems: 'flex-start', + paddingHorizontal:4 + }, + circle: { + borderWidth: 1, + borderRadius: 10000, + alignItems: 'center', + justifyContent: 'center' + }, + icon: { + borderWidth: 1, + borderRadius: 10000, + alignItems: 'center', + justifyContent: 'center' + }, + circleFill: { + borderWidth: 1, + borderRadius: 10000 + }, + text: { + fontSize: 16, + fontWeight: '700', + fontFamily: 'Poppins-Regular' + } +}); + +/* Props ======================================= */ +RadioButtonRN.propTypes = { + style: PropTypes.object, + boxStyle: PropTypes.object, + textStyle: PropTypes.object, + initial: PropTypes.number, + circleSize: PropTypes.number, + duration: PropTypes.number, + data: PropTypes.array, + animationTypes: PropTypes.array, + selectedBtn: PropTypes.func, + activeColor: PropTypes.string, + deactiveColor: PropTypes.string, + textActiveColor: PropTypes.string, + textDeactiveColor: PropTypes.string, + boxActiveBgColor: PropTypes.string, + boxDeactiveBgColor: PropTypes.string, + textColor: PropTypes.string, + box: PropTypes.bool, +}; + +RadioButtonRN.defaultProps = { + style: {}, + boxStyle: {}, + textStyle: {}, + initial: -1, + circleSize: 18, + duration: 500, + data: [], + animationTypes: [], + selectedBtn: () => {}, + activeColor: '#03a9f4', + deactiveColor: '#e2e2e2', + boxActiveBgColor: '#e1f5fe33', + boxDeactiveBgColor: '#fff', + textColor: '#383838', + box: true, +}; + +/* Export Component ============================ */ +export default RadioButtonRN; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..3c4d4e7 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "radio-buttons-react-native", + "version": "1.0.0", + "description": "Animated radio buttons component for react native", + "main": "RadioButtonRN.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + + "repository": { + "type": "git", + "url": "git+https://github.com/sramezani/radio-buttons-react-native" + }, + "keywords": [ + "react-component", + "react-native", + "ios", + "android", + "form", + "button", + "radio-button", + "radio-buttons", + "react-native-radio-button", + "animated", + "react", + "mobile" + ], + "author": "Siamak Ramezani ", + "license": "MIT", + "bugs": { + "url": "https://github.com/sramezani/radio-buttons-react-native/issues" + }, + "homepage": "https://github.com/sramezani/radio-buttons-react-native#readme" + } +