UNPKG

material-ui

Version:

Material Design UI components built with React

203 lines (168 loc) 5.44 kB
const React = require('react'); const ReactDOM = require('react-dom'); const TabTemplate = require('./tabTemplate'); const InkBar = require('../ink-bar'); const StylePropable = require('../mixins/style-propable'); const Controllable = require('../mixins/controllable'); const DefaultRawTheme = require('../styles/raw-themes/light-raw-theme'); const ThemeManager = require('../styles/theme-manager'); const Tabs = React.createClass({ mixins: [StylePropable, Controllable], contextTypes: { muiTheme: React.PropTypes.object, }, propTypes: { contentContainerStyle: React.PropTypes.object, initialSelectedIndex: React.PropTypes.number, inkBarStyle: React.PropTypes.object, tabItemContainerStyle: React.PropTypes.object, }, //for passing default theme context to children childContextTypes: { muiTheme: React.PropTypes.object, }, getChildContext () { return { muiTheme: this.state.muiTheme, }; }, getDefaultProps() { return { initialSelectedIndex : 0, }; }, getInitialState(){ let valueLink = this.getValueLink(this.props); let initialIndex = this.props.initialSelectedIndex; return { selectedIndex: valueLink.value ? this._getSelectedIndex(this.props) : initialIndex < this.getTabCount() ? initialIndex : 0, muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), }; }, getEvenWidth(){ return ( parseInt(window .getComputedStyle(ReactDOM.findDOMNode(this)) .getPropertyValue('width'), 10) ); }, getTabCount() { return React.Children.count(this.props.children); }, componentWillReceiveProps(newProps, nextContext) { let valueLink = this.getValueLink(newProps); let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; if (valueLink.value){ this.setState({selectedIndex: this._getSelectedIndex(newProps)}); } this.setState({muiTheme: newMuiTheme}); }, render() { let { children, contentContainerStyle, initialSelectedIndex, inkBarStyle, style, tabWidth, tabItemContainerStyle, ...other, } = this.props; let themeVariables = this.state.muiTheme.tabs; let styles = { tabItemContainer: { margin: 0, padding: 0, width: '100%', height: 48, backgroundColor: themeVariables.backgroundColor, whiteSpace: 'nowrap', display: 'table', }, }; let valueLink = this.getValueLink(this.props); let tabValue = valueLink.value; let tabContent = []; let width = 100 / this.getTabCount() +'%'; let left = 'calc(' + width + '*' + this.state.selectedIndex + ')'; let tabs = React.Children.map(children, (tab, index) => { if (tab.type.displayName === "Tab") { if (!tab.props.value && tabValue && process.env.NODE_ENV !== 'production') { console.error('Tabs value prop has been passed, but Tab ' + index + ' does not have a value prop. Needs value if Tabs is going' + ' to be a controlled component.'); } tabContent.push(tab.props.children ? React.createElement(TabTemplate, { key: index, selected: this._getSelected(tab, index), }, tab.props.children) : undefined); return React.cloneElement(tab, { key: index, selected: this._getSelected(tab, index), tabIndex: index, width: width, onTouchTap: this._handleTabTouchTap, }); } else { let type = tab.type.displayName || tab.type; console.error('Tabs only accepts Tab Components as children. Found ' + type + ' as child number ' + (index + 1) + ' of Tabs'); } }, this); let inkBar = this.state.selectedIndex !== -1 ? ( <InkBar left={left} width={width} style={inkBarStyle}/> ) : null; let inkBarContainerWidth = tabItemContainerStyle ? tabItemContainerStyle.width : '100%'; return ( <div {...other} style={this.prepareStyles(style)}> <div style={this.prepareStyles(styles.tabItemContainer, tabItemContainerStyle)}> {tabs} </div> <div style={{width: inkBarContainerWidth}}> {inkBar} </div> <div style={this.prepareStyles(contentContainerStyle)}> {tabContent} </div> </div> ); }, _getSelectedIndex(props) { let valueLink = this.getValueLink(props); let selectedIndex = -1; React.Children.forEach(props.children, (tab, index) => { if (valueLink.value === tab.props.value) { selectedIndex = index; } }); return selectedIndex; }, _handleTabTouchTap(value, e, tab){ let valueLink = this.getValueLink(this.props); let tabIndex = tab.props.tabIndex; if ((valueLink.value && valueLink.value !== value) || this.state.selectedIndex !== tabIndex) { valueLink.requestChange(value, e, tab); } this.setState({selectedIndex: tabIndex}); tab.props.onActive(tab); }, _getSelected(tab, index) { let valueLink = this.getValueLink(this.props); return valueLink.value ? valueLink.value === tab.props.value : this.state.selectedIndex === index; }, }); module.exports = Tabs;