From 1a5b017defa0b6f23a84dd6a7ceba69200983c61 Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Tue, 25 Oct 2016 13:44:29 +0200 Subject: [PATCH 01/10] automatically re-calculate the height automatically re-calculate the height when the content updates. --- src/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 8da182b..a6048d1 100644 --- a/src/index.js +++ b/src/index.js @@ -81,7 +81,15 @@ var Accordion = React.createClass({ }); } }, - + + componentWillReceiveProps(nextProps) { + // Recalculate the height only if the Accordion is open + if(!this.state.is_visible) + { + setTimeout(this._getContentHeight); + } + }, + componentDidMount() { // Gets content height when component mounts // without setTimeout, measure returns 0 for every value. From ba0f0055ad2355af05bdc50a37a2a15570aa5323 Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Mon, 21 Nov 2016 07:05:09 +0100 Subject: [PATCH 02/10] fix doesn't work on RN > 0.36 --- src/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index a6048d1..f5eeb14 100644 --- a/src/index.js +++ b/src/index.js @@ -116,7 +116,8 @@ var Accordion = React.createClass({ From c326bb51ea2e9abe838ef98a3a3f23a7900781cc Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Mon, 21 Nov 2016 07:16:16 +0100 Subject: [PATCH 03/10] Active styles + different header when expanded Cherry picking from 8a801c7c1cbab3d15f6d683bdbabed7bf3b8de7e and b6dc7455277218c517dc175697955fc8a877655a https://github.com/naoufal/react-native-accordion/pull/38 --- src/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index f5eeb14..edc5576 100644 --- a/src/index.js +++ b/src/index.js @@ -20,9 +20,11 @@ var Accordion = React.createClass({ easing: React.PropTypes.string, expanded: React.PropTypes.bool, header: React.PropTypes.element.isRequired, + headerOpen: React.PropTypes.element, onPress: React.PropTypes.func, underlayColor: React.PropTypes.string, - style: React.PropTypes.object + style: React.PropTypes.object, + styleOpen: React.PropTypes.object, }, getDefaultProps() { @@ -109,9 +111,9 @@ var Accordion = React.createClass({ ref="AccordionHeader" onPress={this._onPress} underlayColor={this.props.underlayColor} - style={this.props.style} + style={this.state.is_visible ? this.props.styleOpen : this.props.style} > - {this.props.header} + {this.state.is_visible && this.props.headerOpen ? this.props.headerOpen : this.props.header} Date: Mon, 19 Dec 2016 21:01:30 +0100 Subject: [PATCH 04/10] Now the component is able to automatically update the height on content change --- package.json | 3 +- src/index.js | 267 ++++++++++++++++++++++++++++----------------------- 2 files changed, 149 insertions(+), 121 deletions(-) diff --git a/package.json b/package.json index 9e625de..f4ccd41 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ }, "homepage": "https://github.com/naoufal/react-native-accordion", "dependencies": { - "react-tween-state": "0.0.5" + "react-tween-state": "0.0.5", + "lodash": "^4.16.6" } } diff --git a/src/index.js b/src/index.js index edc5576..905835d 100644 --- a/src/index.js +++ b/src/index.js @@ -4,132 +4,159 @@ import React, { PropTypes } from 'react'; import tweenState from 'react-tween-state'; import { - StyleSheet, - TouchableHighlight, - View, - Text + StyleSheet, + TouchableHighlight, + View, + Text } from 'react-native'; +var _ = require('lodash'); + 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, - headerOpen: React.PropTypes.element, - onPress: React.PropTypes.func, - underlayColor: React.PropTypes.string, - style: React.PropTypes.object, - styleOpen: React.PropTypes.object, - }, - - getDefaultProps() { - return { - activeOpacity: 1, - animationDuration: 300, - easing: 'linear', - expanded: false, - underlayColor: '#000', - style: {} - }; - }, - - getInitialState() { - return { - is_visible: false, - height: 0, - content_height: 0 - }; - }, - - close() { - this.state.is_visible && this.toggle(); - }, - - open() { - !this.state.is_visible && this.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 - }); - }, - - _onPress() { - this.toggle(); - - if (this.props.onPress) { - this.props.onPress.call(this); - } - }, - - _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, - content_height: height + 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, + headerOpen: React.PropTypes.element, + onPress: React.PropTypes.func, + underlayColor: React.PropTypes.string, + style: React.PropTypes.object, + styleOpen: React.PropTypes.object, + }, + + getDefaultProps() { + return { + activeOpacity: 1, + animationDuration: 300, + easing: 'linear', + expanded: false, + underlayColor: '#000', + style: {} + }; + }, + + getInitialState() { + return { + is_visible: false, + height: 0, + content_height: 0 + }; + }, + + close() { + this.state.is_visible && this.toggle(); + }, + + open() { + !this.state.is_visible && this.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 }); - }); - } - }, - - componentWillReceiveProps(nextProps) { - // Recalculate the height only if the Accordion is open - if(!this.state.is_visible) - { + }, + + _onPress() { + this.toggle(); + + if (this.props.onPress) { + this.props.onPress.call(this); + } + }, + + _getContentHeight(onlyOpen = false) { + if (this.refs.AccordionContent) { + this.refs.AccordionContent.measure((ox, oy, width, height, px, py) => { + // Sets content height in state + if(onlyOpen) + { + this.setState({ + height: height, + content_height: height + }); + } + else + { + this.setState({ + height: this.props.expanded ? height : 0, + content_height: height + }); + } + + }); + } + }, + + componentWillReceiveProps(nextProps) { + // Recalculate the height only if the Accordion is open + if(!this.state.is_visible) + { + setTimeout(this._getContentHeight); + } + }, + + + /** + * Check if our accordion has received new content (children). If yes, and the current item is + * open recalculate the height of that open item + * + * @param prevProps + * @param prevState + */ + componentDidUpdate(prevProps, prevState) { + if(this.state.is_visible && !_.isEqual(prevProps.content, this.props.content)){ + setTimeout(() => this._getContentHeight(true)); + } + }, + + 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.state.is_visible && this.props.headerOpen ? this.props.headerOpen : this.props.header} + + + + {this.props.content} + + + + /*jshint ignore:end */ + ); } - }, - - 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.state.is_visible && this.props.headerOpen ? this.props.headerOpen : this.props.header} - - - - {this.props.content} - - - - /*jshint ignore:end */ - ); - } }); module.exports = Accordion; From 38f18710534bd7510747bee3bb2db69b7cf9abf8 Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Wed, 1 Mar 2017 18:54:26 +0100 Subject: [PATCH 05/10] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b0e3907..61c8fa4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules npm-debug.log .DS_Store +.idea From 3050cfae79f07da92a67532e5897a9046153adb6 Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Wed, 1 Mar 2017 18:57:18 +0100 Subject: [PATCH 06/10] Android fixes for the content height Android fixes for the content height adding the fixes specified in this issue: https://github.com/naoufal/react-native-accordion/pull/19 without them the content item is behind the currently open element --- src/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 905835d..c22e97b 100644 --- a/src/index.js +++ b/src/index.js @@ -148,8 +148,9 @@ var Accordion = React.createClass({ height: this.getTweeningValue('height'), overflow: 'scroll' }} + onLayout={()=>{}} > - + {}}> {this.props.content} From 721dc70bf5f8339ac1d946be78253ee40f06920d Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Wed, 1 Mar 2017 18:58:06 +0100 Subject: [PATCH 07/10] Adding onEnd property Adding onEnd property Helps when you need something to update in response of the open/close of the accordion. --- src/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index c22e97b..9de8aaa 100644 --- a/src/index.js +++ b/src/index.js @@ -62,7 +62,8 @@ var Accordion = React.createClass({ this.tweenState('height', { easing: tweenState.easingTypes[this.props.easing], duration: this.props.animationDuration, - endValue: this.state.height === 0 ? this.state.content_height : 0 + endValue: this.state.height === 0 ? this.state.content_height : 0, + onEnd: () => {this.props.onEnd && this.props.onEnd()} }); }, From 4b1a3e3b89ff39b93042b570cb93fff90f0b0caa Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Thu, 2 Mar 2017 07:48:48 +0100 Subject: [PATCH 08/10] Let the accordion trigger a longPress click as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit You can not have 2 touchable element nested in each other and have them behave as expected. That’s why if we want to react on onPress and onLongPress we have to do it on the same touchable element. --- src/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/index.js b/src/index.js index 9de8aaa..8addbb4 100644 --- a/src/index.js +++ b/src/index.js @@ -75,6 +75,12 @@ var Accordion = React.createClass({ } }, + _onLongPress() { + if (this.props.onLongPress) { + this.props.onLongPress.call(this); + } + }, + _getContentHeight(onlyOpen = false) { if (this.refs.AccordionContent) { this.refs.AccordionContent.measure((ox, oy, width, height, px, py) => { @@ -138,6 +144,7 @@ var Accordion = React.createClass({ From d5b729e07bcc92ff4b9dab5fef94ede077af114d Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Wed, 15 Mar 2017 11:56:36 +0100 Subject: [PATCH 09/10] the expanded property was not respected. Because of this we couldn't show the correct open header when we first render the component --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 8addbb4..0b6ea93 100644 --- a/src/index.js +++ b/src/index.js @@ -42,7 +42,7 @@ var Accordion = React.createClass({ getInitialState() { return { - is_visible: false, + is_visible: this.props.expanded, height: 0, content_height: 0 }; From da85cd6ad832b38c4c9c7c332eeb2969133ea498 Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Tue, 27 Jun 2017 12:40:36 +0200 Subject: [PATCH 10/10] Update dependency of react-tween-state to v0.1.5 0.0.5 was showing an isMounted warning with the latest RN --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4ccd41..614fb8b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ }, "homepage": "https://github.com/naoufal/react-native-accordion", "dependencies": { - "react-tween-state": "0.0.5", + "react-tween-state": "0.1.5", "lodash": "^4.16.6" } }