UNPKG

apsl-react-native-button

Version:

React Native button component with rounded corners.

154 lines (144 loc) 4.07 kB
'use strict'; import React, { Component } from 'react'; import { View, TouchableOpacity, Text, StyleSheet, ActivityIndicator, TouchableNativeFeedback, Platform } from 'react-native'; import PropTypes from 'prop-types'; import isEqual from 'lodash.isequal'; class Button extends Component { static propTypes = { textStyle: Text.propTypes.style, disabledStyle: Text.propTypes.style, children: PropTypes.oneOfType([ PropTypes.string, PropTypes.node, PropTypes.element ]), testID: PropTypes.string, accessibilityLabel: PropTypes.string, activeOpacity: PropTypes.number, allowFontScaling: PropTypes.bool, isLoading: PropTypes.bool, isDisabled: PropTypes.bool, activityIndicatorColor: PropTypes.string, delayLongPress: PropTypes.number, delayPressIn: PropTypes.number, delayPressOut: PropTypes.number, onPress: PropTypes.func, onLongPress: PropTypes.func, onPressIn: PropTypes.func, onPressOut: PropTypes.func, background: (TouchableNativeFeedback.propTypes) ? TouchableNativeFeedback.propTypes.background : PropTypes.any, } static isAndroid = (Platform.OS === 'android') _renderChildren() { let childElements = []; React.Children.forEach(this.props.children, (item) => { if (typeof item === 'string' || typeof item === 'number') { const element = ( <Text style={[styles.textButton, this.props.textStyle]} allowFontScaling={this.props.allowFontScaling} key={item}> {item} </Text> ); childElements.push(element); } else if (React.isValidElement(item)) { childElements.push(item); } }); return (childElements); } shouldComponentUpdate(nextProps, nextState) { if (!isEqual(nextProps, this.props)) { return true; } return false; } _renderInnerText() { if (this.props.isLoading) { return ( <ActivityIndicator animating={true} size='small' style={styles.spinner} color={this.props.activityIndicatorColor || 'black'} /> ); } return this._renderChildren(); } render() { if (this.props.isDisabled === true || this.props.isLoading === true) { return ( <View style={[styles.button, this.props.style, (this.props.disabledStyle || styles.opacity)]}> {this._renderInnerText()} </View> ); } // Extract Touchable props let touchableProps = { testID: this.props.testID, accessibilityLabel: this.props.accessibilityLabel, onPress: this.props.onPress, onPressIn: this.props.onPressIn, onPressOut: this.props.onPressOut, onLongPress: this.props.onLongPress, activeOpacity: this.props.activeOpacity, delayLongPress: this.props.delayLongPress, delayPressIn: this.props.delayPressIn, delayPressOut: this.props.delayPressOut, }; if (Button.isAndroid) { touchableProps = Object.assign(touchableProps, { background: this.props.background || TouchableNativeFeedback.SelectableBackground() }); return ( <TouchableNativeFeedback {...touchableProps}> <View style={[styles.button, this.props.style]}> {this._renderInnerText()} </View> </TouchableNativeFeedback> ) } else { return ( <TouchableOpacity {...touchableProps} style={[styles.button, this.props.style]}> {this._renderInnerText()} </TouchableOpacity> ); } } } const styles = StyleSheet.create({ button: { height: 44, flexDirection: 'row', alignItems: 'center', borderWidth: 1, borderRadius: 8, marginBottom: 10, alignSelf: 'stretch', justifyContent: 'center', }, textButton: { flex: 1, fontSize: 18, textAlign: 'center', backgroundColor: 'transparent', }, spinner: { alignSelf: 'center', }, opacity: { opacity: 0.5, }, }); module.exports = Button;