material-ui
Version:
Material Design UI components built with React
180 lines (153 loc) • 4.9 kB
JSX
const React = require('react');
const PureRenderMixin = require('react-addons-pure-render-mixin');
const StylePropable = require('../mixins/style-propable');
const Colors = require('../styles/colors');
const CheckIcon = require('../svg-icons/navigation/check');
const ListItem = require('../lists/list-item');
const DefaultRawTheme = require('../styles/raw-themes/light-raw-theme');
const ThemeManager = require('../styles/theme-manager');
const MenuItem = React.createClass({
mixins: [PureRenderMixin, StylePropable],
contextTypes: {
muiTheme: React.PropTypes.object,
},
propTypes: {
checked: React.PropTypes.bool,
desktop: React.PropTypes.bool,
disabled: React.PropTypes.bool,
innerDivStyle: React.PropTypes.object,
insetChildren: React.PropTypes.bool,
focusState: React.PropTypes.oneOf([
'none',
'focused',
'keyboard-focused',
]),
leftIcon: React.PropTypes.element,
rightIcon: React.PropTypes.element,
secondaryText: React.PropTypes.node,
value: React.PropTypes.string,
},
//for passing default theme context to children
childContextTypes: {
muiTheme: React.PropTypes.object,
},
getChildContext () {
return {
muiTheme: this.state.muiTheme,
};
},
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});
},
getDefaultProps() {
return {
focusState: 'none',
};
},
componentDidMount() {
this._applyFocusState();
},
componentDidUpdate() {
this._applyFocusState();
},
render() {
const {
checked,
children,
desktop,
disabled,
focusState,
innerDivStyle,
insetChildren,
leftIcon,
rightIcon,
secondaryText,
style,
value,
...other,
} = this.props;
const disabledColor = this.state.muiTheme.rawTheme.palette.disabledColor;
const textColor = this.state.muiTheme.rawTheme.palette.textColor;
const leftIndent = desktop ? 64 : 72;
const sidePadding = desktop ? 24 : 16;
const styles = {
root: {
color: disabled ? disabledColor : textColor,
lineHeight: desktop ? '32px' : '48px',
fontSize: desktop ? 15 : 16,
whiteSpace: 'nowrap',
},
innerDivStyle: {
paddingLeft: leftIcon || insetChildren || checked ? leftIndent : sidePadding,
paddingRight: sidePadding,
paddingBottom: 0,
paddingTop: 0,
},
secondaryText: {
float: 'right',
},
leftIconDesktop: {
padding: 0,
left: 24,
top: 4,
},
rightIconDesktop: {
padding: 0,
right: 24,
top: 4,
fill: Colors.grey600,
},
};
let mergedRootStyles = this.mergeStyles(styles.root, style);
let mergedInnerDivStyles = this.mergeStyles(styles.innerDivStyle, innerDivStyle);
//Left Icon
let leftIconElement = leftIcon ? leftIcon : checked ? <CheckIcon /> : null;
if (leftIconElement && desktop) {
const mergedLeftIconStyles = this.mergeStyles(styles.leftIconDesktop, leftIconElement.props.style);
leftIconElement = React.cloneElement(leftIconElement, {style: mergedLeftIconStyles});
}
//Right Icon
let rightIconElement;
if (rightIcon) {
const mergedRightIconStyles = desktop ?
this.mergeStyles(styles.rightIconDesktop, rightIcon.props.style) : null;
rightIconElement = React.cloneElement(rightIcon, {style: mergedRightIconStyles});
}
//Secondary Text
let secondaryTextElement;
if (secondaryText) {
const secondaryTextIsAnElement = React.isValidElement(secondaryText);
const mergedSecondaryTextStyles = secondaryTextIsAnElement ?
this.mergeStyles(styles.secondaryText, secondaryText.props.style) : null;
secondaryTextElement = secondaryTextIsAnElement ?
React.cloneElement(secondaryText, {style: mergedSecondaryTextStyles}) :
<div style={this.prepareStyles(styles.secondaryText)}>{secondaryText}</div>;
}
return (
<ListItem
{...other}
disabled={disabled}
innerDivStyle={mergedInnerDivStyles}
insetChildren={insetChildren}
leftIcon={leftIconElement}
ref="listItem"
rightIcon={rightIconElement}
style={mergedRootStyles}>
{children}
{secondaryTextElement}
</ListItem>
);
},
_applyFocusState() {
this.refs.listItem.applyFocusState(this.props.focusState);
},
});
module.exports = MenuItem;