UNPKG

material-ui

Version:

Material Design UI components built with React

268 lines (233 loc) 7.34 kB
import React from 'react'; import ReactDOM from 'react-dom'; import StylePropable from '../mixins/style-propable'; import DefaultRawTheme from '../styles/raw-themes/light-raw-theme'; import ThemeManager from '../styles/theme-manager'; const Table = React.createClass({ propTypes: { allRowsSelected: React.PropTypes.bool, bodyStyle: React.PropTypes.object, children: React.PropTypes.node, /** * The css class name of the root element. */ className: React.PropTypes.string, fixedFooter: React.PropTypes.bool, fixedHeader: React.PropTypes.bool, footerStyle: React.PropTypes.object, headerStyle: React.PropTypes.object, height: React.PropTypes.string, multiSelectable: React.PropTypes.bool, onCellClick: React.PropTypes.func, onCellHover: React.PropTypes.func, onCellHoverExit: React.PropTypes.func, onRowHover: React.PropTypes.func, onRowHoverExit: React.PropTypes.func, onRowSelection: React.PropTypes.func, selectable: React.PropTypes.bool, /** * Override the inline-styles of the root element. */ style: React.PropTypes.object, wrapperStyle: React.PropTypes.object, }, contextTypes: { muiTheme: React.PropTypes.object, }, //for passing default theme context to children childContextTypes: { muiTheme: React.PropTypes.object, }, mixins: [StylePropable], getDefaultProps() { return { allRowsSelected: false, fixedFooter: true, fixedHeader: true, height: 'inherit', multiSelectable: false, selectable: true, }; }, getInitialState() { return { muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), allRowsSelected: this.props.allRowsSelected, }; }, getChildContext() { return { muiTheme: this.state.muiTheme, }; }, //to update theme inside state whenever a new theme is passed down //from the parent / owner using context componentWillReceiveProps(nextProps, nextContext) { let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; this.setState({muiTheme: newMuiTheme}); }, getTheme() { return this.state.muiTheme.table; }, getStyles() { let styles = { root: { backgroundColor: this.getTheme().backgroundColor, padding: '0 ' + this.state.muiTheme.rawTheme.spacing.desktopGutter + 'px', width: '100%', borderCollapse: 'collapse', borderSpacing: 0, tableLayout: 'fixed', fontFamily: this.state.muiTheme.rawTheme.fontFamily, }, bodyTable: { height: (this.props.fixedHeader || this.props.fixedFooter) ? this.props.height : 'auto', overflowX: 'hidden', overflowY: 'auto', }, tableWrapper: { height: (this.props.fixedHeader || this.props.fixedFooter) ? 'auto' : this.props.height, overflow: 'auto', }, }; return styles; }, isScrollbarVisible() { const tableDivHeight = ReactDOM.findDOMNode(this.refs.tableDiv).clientHeight; const tableBodyHeight = ReactDOM.findDOMNode(this.refs.tableBody).clientHeight; return tableBodyHeight > tableDivHeight; }, _createTableHeader(base) { return React.cloneElement( base, { enableSelectAll: base.props.enableSelectAll && this.props.selectable && this.props.multiSelectable, onSelectAll: this._onSelectAll, selectAllSelected: this.state.allRowsSelected, } ); }, _createTableBody(base) { return React.cloneElement( base, { allRowsSelected: this.state.allRowsSelected, multiSelectable: this.props.multiSelectable, onCellClick: this._onCellClick, onCellHover: this._onCellHover, onCellHoverExit: this._onCellHoverExit, onRowHover: this._onRowHover, onRowHoverExit: this._onRowHoverExit, onRowSelection: this._onRowSelection, selectable: this.props.selectable, style: this.mergeAndPrefix({height: this.props.height}, base.props.style), } ); }, _createTableFooter(base) { return base; }, _onCellClick(rowNumber, columnNumber) { if (this.props.onCellClick) this.props.onCellClick(rowNumber, columnNumber); }, _onCellHover(rowNumber, columnNumber) { if (this.props.onCellHover) this.props.onCellHover(rowNumber, columnNumber); }, _onCellHoverExit(rowNumber, columnNumber) { if (this.props.onCellHoverExit) this.props.onCellHoverExit(rowNumber, columnNumber); }, _onRowHover(rowNumber) { if (this.props.onRowHover) this.props.onRowHover(rowNumber); }, _onRowHoverExit(rowNumber) { if (this.props.onRowHoverExit) this.props.onRowHoverExit(rowNumber); }, _onRowSelection(selectedRows) { if (this.state.allRowsSelected) this.setState({allRowsSelected: false}); if (this.props.onRowSelection) this.props.onRowSelection(selectedRows); }, _onSelectAll() { if (this.props.onRowSelection) { if (!this.state.allRowsSelected) { this.props.onRowSelection('all'); } else { this.props.onRowSelection('none'); } } this.setState({allRowsSelected: !this.state.allRowsSelected}); }, render() { let { children, className, fixedFooter, fixedHeader, style, wrapperStyle, headerStyle, bodyStyle, footerStyle, ...other, } = this.props; let styles = this.getStyles(); let tHead, tFoot, tBody; for (let child of children) { if (!React.isValidElement(child)) continue; let displayName = child.type.displayName; if (displayName === 'TableBody') { tBody = this._createTableBody(child); } else if (displayName === 'TableHeader') { tHead = this._createTableHeader(child); } else if (displayName === 'TableFooter') { tFoot = this._createTableFooter(child); } } // If we could not find a table-header and a table-body, do not attempt to display anything. if (!tBody && !tHead) return null; let mergedTableStyle = this.prepareStyles(styles.root, style); let headerTable, footerTable; let inlineHeader, inlineFooter; if (fixedHeader) { headerTable = ( <div style={this.prepareStyles(headerStyle)}> <table className={className} style={mergedTableStyle}> {tHead} </table> </div> ); } else { inlineHeader = tHead; } if (tFoot !== undefined) { if (fixedFooter) { footerTable = ( <div style={this.prepareStyles(footerStyle)}> <table className={className} style={mergedTableStyle}> {tFoot} </table> </div> ); } else { inlineFooter = tFoot; } } return ( <div style={this.prepareStyles(styles.tableWrapper, wrapperStyle)}> {headerTable} <div style={this.prepareStyles(styles.bodyTable, bodyStyle)} ref="tableDiv"> <table className={className} style={mergedTableStyle} ref="tableBody"> {inlineHeader} {inlineFooter} {tBody} </table> </div> {footerTable} </div> ); }, }); export default Table;