From 32a7dc9515e614f4ffd599d506aa207c4c6ad289 Mon Sep 17 00:00:00 2001 From: Elliot Hesp Date: Sun, 27 Dec 2015 13:02:31 +0000 Subject: [PATCH] Create a generic IconToggle component --- lib/IconToggle.js | 173 ++++++++++++++++++++++++++++++++++++++++++++++ lib/index.js | 3 +- 2 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 lib/IconToggle.js diff --git a/lib/IconToggle.js b/lib/IconToggle.js new file mode 100644 index 0000000..b56f228 --- /dev/null +++ b/lib/IconToggle.js @@ -0,0 +1,173 @@ +import React, { Component, StyleSheet, PropTypes, Text, View, Animated, Dimensions } from 'react-native'; +import { TYPO, PRIMARY, COLOR, PRIMARY_COLORS, THEME_NAME } from './config'; +import { getColor } from './helpers'; +import Icon from './Icon'; + +export default class IconToggle extends Component { + + constructor(props) { + super(props); + this.state = { + scaleValue: new Animated.Value(0.001), + opacityValue: new Animated.Value(0.1), + maxOpacity: props.opacity, + size: null + }; + this._responder = { + onStartShouldSetResponder: (e) => true, + onResponderGrant: this._highlight, + onResponderRelease: this._handleResponderEnd, + onResponderTerminate: this._unHighlight + }; + } + + static propTypes = { + color: PropTypes.string.isRequired, + opacity: PropTypes.number, + disabled: PropTypes.bool, + onPress: PropTypes.func, + percent: PropTypes.number, + children: PropTypes.element.isRequired, + badge: PropTypes.shape({ + value: PropTypes.number, + backgroundColor: PropTypes.string, + textColor: PropTypes.string + }) + }; + + static defaultProps = { + opacity: .1, + disabled: false, + percent: 90, + }; + + setSize = (event) => { + const {x, y, width, height} = event.nativeEvent.layout; + + this.setState({ + size: width > height ? width : height + }); + } + + render() { + const { scaleValue, opacityValue, size } = this.state; + const { color, children } = this.props; + + let { badge } = this.props; + let { percent } = this.props; + + if (percent < 0) { + percent = 0; + } + if (percent > 100) { + percent = 100; + } + + if (badge && typeof badge.value === 'number') { + badge = Object.assign({}, + { value: badge.value }, + badge.backgroundColor ? { backgroundColor: badge.backgroundColor } : { backgroundColor: 'paperRed'}, + badge.textColor ? { textColor: badge.textColor } : { textColor: '#ffffff' } + ); + } + percent = percent / 100; + + return ( + + + {size && + + } + { this.setSize(event) }}> + {children} + + {size && badge && typeof badge.value === 'number' && + + + {badge.value} + + + } + + + ); + }; + + /** + * + * @private + */ + _highlight = () => { + if (!this.props.disabled) { + Animated.timing(this.state.scaleValue, { + toValue: 1, + duration: 150 + }).start(); + Animated.timing(this.state.opacityValue, { + toValue: this.state.maxOpacity, + duration: 100 + }).start(); + } + }; + + /** + * + * @private + */ + _unHighlight = () => { + if (!this.props.disabled) { + Animated.timing(this.state.scaleValue, { + toValue: 0.001, + duration: 1500 + }).start(); + Animated.timing(this.state.opacityValue, { + toValue: 0 + }).start(); + } + }; + + /** + * + * @private + */ + _handleResponderEnd = () => { + const { disabled, onPress } = this.props; + + if (!disabled) { + this._unHighlight(); + onPress && onPress(); + } + }; +} + +const styles = { + badgeContainer: { + position: 'absolute', + borderRadius: 7, + width: 15, + height: 15 + }, + badgeText: { + lineHeight: 10, + textAlign: 'center', + fontSize: 10, + paddingTop: 8 + } +}; \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index 90eaa77..5da465b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -7,10 +7,9 @@ export { default as CheckboxGroup } from './CheckboxGroup'; export { default as Drawer } from './Drawer'; export { default as Divider } from './Divider'; export { default as Icon } from './Icon'; -export { default as IconButton } from './IconButton'; +export { default as IconToggle } from './IconToggle'; export { default as List } from './List'; export { default as RadioButton } from './RadioButton'; export { default as RadioButtonGroup } from './RadioButtonGroup'; -export { default as Ripple } from './Ripple'; export { default as Subheader } from './Subheader'; export { default as Toolbar } from './Toolbar'; \ No newline at end of file