UNPKG

d2-ui

Version:
142 lines (116 loc) 4.01 kB
import React from 'react'; import getMuiTheme from '../styles/getMuiTheme'; import StylePropable from '../mixins/style-propable'; import ColorManipulator from '../utils/color-manipulator'; export const SelectableContainerEnhance = (Component) => { const composed = React.createClass({ displayName: `Selectable${Component.displayName}`, propTypes: { children: React.PropTypes.node, selectedItemStyle: React.PropTypes.object, valueLink: React.PropTypes.shape({ value: React.PropTypes.any, requestChange: React.PropTypes.func, }).isRequired, }, contextTypes: { muiTheme: React.PropTypes.object, }, childContextTypes: { muiTheme: React.PropTypes.object, }, mixins: [ StylePropable, ], getInitialState() { return { muiTheme: this.context.muiTheme || getMuiTheme(), }; }, getChildContext() { return { muiTheme: this.state.muiTheme, }; }, componentWillReceiveProps(nextProps, nextContext) { let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; this.setState({muiTheme: newMuiTheme}); }, getValueLink: function(props) { return props.valueLink || { value: props.value, requestChange: props.onChange, }; }, extendChild(child, styles, selectedItemStyle) { if (child && child.type && child.type.displayName === 'ListItem') { let selected = this.isChildSelected(child, this.props); let selectedChildrenStyles = {}; if (selected) { selectedChildrenStyles = this.mergeStyles(styles, selectedItemStyle); } let mergedChildrenStyles = this.mergeStyles(child.props.style || {}, selectedChildrenStyles); this.keyIndex += 1; return React.cloneElement(child, { onTouchTap: (e) => { this.handleItemTouchTap(e, child); if (child.props.onTouchTap) { child.props.onTouchTap(e); } }, key: this.keyIndex, style: mergedChildrenStyles, nestedItems: child.props.nestedItems.map((child) => this.extendChild(child, styles, selectedItemStyle)), initiallyOpen: this.isInitiallyOpen(child), }); } else { return child; } }, isInitiallyOpen(child) { if (child.props.initiallyOpen) { return child.props.initiallyOpen; } return this.hasSelectedDescendant(false, child); }, hasSelectedDescendant(previousValue, child) { if (React.isValidElement(child) && child.props.nestedItems && child.props.nestedItems.length > 0) { return child.props.nestedItems.reduce(this.hasSelectedDescendant, previousValue); } return previousValue || this.isChildSelected(child, this.props); }, isChildSelected(child, props) { let itemValue = this.getValueLink(props).value; let childValue = child.props.value; return (itemValue === childValue); }, handleItemTouchTap(e, item) { let valueLink = this.getValueLink(this.props); let itemValue = item.props.value; let menuValue = valueLink.value; if ( itemValue !== menuValue) { valueLink.requestChange(e, itemValue); } }, render() { const {children, selectedItemStyle} = this.props; this.keyIndex = 0; let styles = {}; if (!selectedItemStyle) { let textColor = this.state.muiTheme.rawTheme.palette.textColor; let selectedColor = ColorManipulator.fade(textColor, 0.2); styles = { backgroundColor: selectedColor, }; } let newChildren = React.Children.map(children, (child) => this.extendChild(child, styles, selectedItemStyle)); return ( <Component {...this.props} {...this.state}> {newChildren} </Component> ); }, }); return composed; }; export default SelectableContainerEnhance;