UNPKG

react-bootstrap

Version:

Bootstrap 3 components build with React

140 lines (117 loc) 3.56 kB
import React, { cloneElement } from 'react'; import BootstrapMixin from './BootstrapMixin'; import ValidComponentChildren from './utils/ValidComponentChildren'; import Nav from './Nav'; import NavItem from './NavItem'; function getDefaultActiveKeyFromChildren(children) { let defaultActiveKey; ValidComponentChildren.forEach(children, function(child) { if (defaultActiveKey == null) { defaultActiveKey = child.props.eventKey; } }); return defaultActiveKey; } const TabbedArea = React.createClass({ mixins: [BootstrapMixin], propTypes: { activeKey: React.PropTypes.any, defaultActiveKey: React.PropTypes.any, bsStyle: React.PropTypes.oneOf(['tabs', 'pills']), animation: React.PropTypes.bool, id: React.PropTypes.string, onSelect: React.PropTypes.func }, getDefaultProps() { return { bsStyle: 'tabs', animation: true }; }, getInitialState() { let defaultActiveKey = this.props.defaultActiveKey != null ? this.props.defaultActiveKey : getDefaultActiveKeyFromChildren(this.props.children); return { activeKey: defaultActiveKey, previousActiveKey: null }; }, componentWillReceiveProps(nextProps) { if (nextProps.activeKey != null && nextProps.activeKey !== this.props.activeKey) { this.setState({ previousActiveKey: this.props.activeKey }); } }, handlePaneAnimateOutEnd() { this.setState({ previousActiveKey: null }); }, render() { let activeKey = this.props.activeKey != null ? this.props.activeKey : this.state.activeKey; function renderTabIfSet(child) { return child.props.tab != null ? this.renderTab(child) : null; } let nav = ( <Nav {...this.props} activeKey={activeKey} onSelect={this.handleSelect} ref="tabs"> {ValidComponentChildren.map(this.props.children, renderTabIfSet, this)} </Nav> ); return ( <div> {nav} <div id={this.props.id} className="tab-content" ref="panes"> {ValidComponentChildren.map(this.props.children, this.renderPane)} </div> </div> ); }, getActiveKey() { return this.props.activeKey != null ? this.props.activeKey : this.state.activeKey; }, renderPane(child, index) { let activeKey = this.getActiveKey(); return cloneElement( child, { active: (child.props.eventKey === activeKey && (this.state.previousActiveKey == null || !this.props.animation)), key: child.key ? child.key : index, animation: this.props.animation, onAnimateOutEnd: (this.state.previousActiveKey != null && child.props.eventKey === this.state.previousActiveKey) ? this.handlePaneAnimateOutEnd : null } ); }, renderTab(child) { let {eventKey, className, tab, disabled } = child.props; return ( <NavItem ref={'tab' + eventKey} eventKey={eventKey} className={className} disabled={disabled}> {tab} </NavItem> ); }, shouldComponentUpdate() { // Defer any updates to this component during the `onSelect` handler. return !this._isChanging; }, handleSelect(key) { if (this.props.onSelect) { this._isChanging = true; this.props.onSelect(key); this._isChanging = false; } else if (key !== this.getActiveKey()) { this.setState({ activeKey: key, previousActiveKey: this.getActiveKey() }); } } }); export default TabbedArea;