UNPKG

material-ui

Version:

Material Design UI components built with React

216 lines (190 loc) 5.52 kB
const React = require('react'); const StylePropable = require('../mixins/style-propable'); const DefaultRawTheme = require('../styles/raw-themes/light-raw-theme'); const ThemeManager = require('../styles/theme-manager'); const GridTile = React.createClass({ mixins: [StylePropable], contextTypes: { muiTheme: React.PropTypes.object, }, propTypes: { title: React.PropTypes.string, subtitle: React.PropTypes.node, titlePosition: React.PropTypes.oneOf(['top', 'bottom']), titleBackground: React.PropTypes.string, actionIcon: React.PropTypes.element, actionPosition: React.PropTypes.oneOf(['left', 'right']), cols: React.PropTypes.number, rows: React.PropTypes.number, rootClass: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.object, ]), }, //for passing default theme context to children childContextTypes: { muiTheme: React.PropTypes.object, }, getChildContext () { return { muiTheme: this.state.muiTheme, }; }, getDefaultProps() { return { titlePosition: 'bottom', titleBackground: 'rgba(0, 0, 0, 0.4)', actionPosition: 'right', cols: 1, rows: 1, rootClass: 'div', }; }, getInitialState () { return { muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), }; }, //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}); }, getStyles() { const spacing = this.state.muiTheme.rawTheme.spacing; const themeVariables = this.state.muiTheme.gridTile; const actionPos = this.props.actionIcon ? this.props.actionPosition : null; const gutterLess = spacing.desktopGutterLess; let styles = { root: { position: 'relative', display: 'block', height: '100%', overflow: 'hidden', }, titleBar: { position: 'absolute', left: 0, right: 0, [this.props.titlePosition]: 0, height: this.props.subtitle ? 68 : 48, background: this.props.titleBackground, display: 'flex', alignItems: 'center', }, titleWrap: { flexGrow: 1, marginLeft: actionPos === 'right' ? gutterLess : 0, marginRight: actionPos === 'left' ? gutterLess : 0, color: themeVariables.textColor, overflow: 'hidden', }, title: { fontSize: '16px', textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap', }, subtitle: { fontSize: '12px', textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap', }, actionIcon: { order: actionPos === 'left' ? -1 : 1, }, childImg: { height: '100%', transform: 'translateX(-50%)', position: 'relative', left: '50%', }, }; return styles; }, componentDidMount() { this._ensureImageCover(); }, componeneDidUpdate() { this._ensureImageCover(); }, _ensureImageCover() { let imgEl = React.findDOMNode(this.refs.img); if (imgEl) { let fit = () => { if (imgEl.offsetWidth < imgEl.parentNode.offsetWidth) { imgEl.style.height = 'auto'; imgEl.style.left = '0'; imgEl.style.width = '100%'; imgEl.style.top = '50%'; imgEl.style.transform = imgEl.style.WebkitTransform = 'translateY(-50%)'; } imgEl.removeEventListener('load', fit); imgEl = null; // prevent closure memory leak }; if (imgEl.complete) { fit(); } else { imgEl.addEventListener('load', fit); } } }, render() { const { title, subtitle, titlePosition, titleBackground, actionIcon, actionPosition, style, children, rootClass, ...other, } = this.props; const styles = this.getStyles(); const mergedRootStyles = this.prepareStyles(styles.root, style); let titleBar = null; if (title) { titleBar = ( <div style={this.prepareStyles(styles.titleBar)}> <div style={this.prepareStyles(styles.titleWrap)}> <div style={this.prepareStyles(styles.title)}>{title}</div> { subtitle ? (<div style={this.prepareStyles(styles.subtitle)}>{subtitle}</div>) : null } </div> { actionIcon ? (<div style={this.prepareStyles(styles.actionIcon)}>{actionIcon}</div>) : null } </div> ); } let newChildren = children; // if there is an image passed as children // clone it an put our styles if (React.Children.count(children) === 1) { newChildren = React.Children.map(children, (child) => { if (child.type === 'img') { return React.cloneElement(child, { ref: 'img', style: this.prepareStyles(styles.childImg, child.props.style), }); } else { return child; } }); } const RootTag = rootClass; return ( <RootTag style={mergedRootStyles} {...other}> {newChildren} {titleBar} </RootTag> ); }, }); module.exports = GridTile;