diff --git a/src/index.js b/src/index.js index 8da182b..ff77594 100644 --- a/src/index.js +++ b/src/index.js @@ -1,97 +1,94 @@ 'use strict'; -import React, { PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import tweenState from 'react-tween-state'; - import { StyleSheet, TouchableHighlight, View, - Text + Text, + Platform, + Animated } from 'react-native'; -var Accordion = React.createClass({ - mixins: [tweenState.Mixin], - - propTypes: { - activeOpacity: React.PropTypes.number, - animationDuration: React.PropTypes.number, - content: React.PropTypes.element.isRequired, - easing: React.PropTypes.string, - expanded: React.PropTypes.bool, - header: React.PropTypes.element.isRequired, - onPress: React.PropTypes.func, - underlayColor: React.PropTypes.string, - style: React.PropTypes.object - }, +const propTypes = { + activeOpacity: PropTypes.number, + animationDuration: PropTypes.number, + content: PropTypes.element.isRequired, + easing: PropTypes.string, + expanded: PropTypes.bool, + header: PropTypes.element.isRequired, + onPress: PropTypes.func, + underlayColor: PropTypes.string, + style: PropTypes.object +}; + +const defaultProps = { + activeOpacity: 1, + animationDuration: 300, + easing: 'linear', + expanded: false, + underlayColor: '#000', + style: {} +}; + +class Accordion extends Component { + state = { + is_visible: false, + height: new Animated.Value(0), + content_height: 0 + }; - getDefaultProps() { - return { - activeOpacity: 1, - animationDuration: 300, - easing: 'linear', - expanded: false, - underlayColor: '#000', - style: {} - }; - }, - - getInitialState() { - return { - is_visible: false, - height: 0, - content_height: 0 - }; - }, + componentDidMount() { + // Gets content height when component mounts + // without setTimeout, measure returns 0 for every value. + // See https://github.com/facebook/react-native/issues/953 + setTimeout(this._getContentHeight); + } - close() { + close = () => { this.state.is_visible && this.toggle(); - }, + }; - open() { + open = () => { !this.state.is_visible && this.toggle(); - }, + }; - toggle() { + toggle = () => { this.state.is_visible = !this.state.is_visible; - this.tweenState('height', { - easing: tweenState.easingTypes[this.props.easing], - duration: this.props.animationDuration, - endValue: this.state.height === 0 ? this.state.content_height : 0 - }); - }, + Animated.timing( + this.state.height, + { + toValue: this.state.height._value === 0 ? this.state.content_height : 0, + duration: this.props.animationDuration, + } + ).start(); + }; - _onPress() { + _onPress = () => { this.toggle(); if (this.props.onPress) { this.props.onPress.call(this); } - }, + }; - _getContentHeight() { + _getContentHeight = () => { if (this.refs.AccordionContent) { this.refs.AccordionContent.measure((ox, oy, width, height, px, py) => { // Sets content height in state this.setState({ - height: this.props.expanded ? height : 0, + height: new Animated.Value(this.props.expanded ? height : 0), content_height: height }); }); } - }, - - componentDidMount() { - // Gets content height when component mounts - // without setTimeout, measure returns 0 for every value. - // See https://github.com/facebook/react-native/issues/953 - setTimeout(this._getContentHeight); - }, + }; render() { return ( - /*jshint ignore:start */ - {this.props.header} + {this.props.header({ isOpen: this.state.is_visible })} - - {this.props.content} + {(Platform.OS === 'ios' || this.state.is_visible) ? this.props.content : null} - + - /*jshint ignore:end */ ); } -}); +} + +Accordion.propTypes = propTypes; +Accordion.defaultProps = defaultProps; -module.exports = Accordion; +export default Accordion;