diff --git a/src/drop-down-menu.jsx b/src/drop-down-menu.jsx index 25de317b0e2e51..748c560ea85e28 100644 --- a/src/drop-down-menu.jsx +++ b/src/drop-down-menu.jsx @@ -4,12 +4,12 @@ import StylePropable from './mixins/style-propable'; import Transitions from './styles/transitions'; import KeyCode from './utils/key-code'; import DropDownArrow from './svg-icons/navigation/arrow-drop-down'; -import Paper from './paper'; -import Menu from './menu/menu'; -import ClearFix from './clearfix'; +import Menu from './menus/menu'; +import MenuItem from './menus/menu-item'; import DefaultRawTheme from './styles/raw-themes/light-raw-theme'; import ThemeManager from './styles/theme-manager'; - +import Popover from './popover/popover'; +import AnimateFromTop from './popover/popover-animate-from-top'; const DropDownMenu = React.createClass({ @@ -107,8 +107,9 @@ const DropDownMenu = React.createClass({ }, control: { cursor: disabled ? 'not-allowed' : 'pointer', - position: 'static', + position: 'relative', height: '100%', + width:'100%', }, controlBg: { transition: Transitions.easeOut(), @@ -124,20 +125,28 @@ const DropDownMenu = React.createClass({ fill: this.state.muiTheme.dropDownMenu.accentColor, }, label: { - transition: Transitions.easeOut(), + //transition: Transitions.easeOut(), lineHeight: spacing.desktopToolbarHeight + 'px', - position: 'absolute', + position: 'relative', paddingLeft: spacing.desktopGutter, + paddingRight: spacing.iconSize + + spacing.desktopGutterLess + + spacing.desktopGutterMini, top: 0, opacity: 1, color: disabled ? this.state.muiTheme.rawTheme.palette.disabledColor : this.state.muiTheme.rawTheme.palette.textColor, }, underline: { + position: 'absolute', borderTop: 'solid 1px ' + accentColor, margin: '-1px ' + spacing.desktopGutter + 'px', + bottom:1, + left:0, + right:0, }, menu: { zIndex: zIndex + 1, + position:'relative', }, menuItem: { paddingRight: spacing.iconSize + @@ -152,15 +161,7 @@ const DropDownMenu = React.createClass({ }, labelWhenOpen: { opacity: 0, - top: spacing.desktopToolbarHeight / 2, - }, - overlay: { - height: '100%', - width: '100%', - position: 'fixed', - top: 0, - left: 0, - zIndex: zIndex, + top: (spacing.desktopToolbarHeight / 8), }, }; @@ -211,17 +212,19 @@ const DropDownMenu = React.createClass({ } } } - let selectedItem = this.props.menuItems[selectedIndex]; if (selectedItem) { - displayValue = selectedItem[labelMember]; + displayValue = selectedItem[labelMember] || selectedItem[displayMember]; } - let menuItems = this.props.menuItems.map((item) => { - item.text = item[displayMember]; - item.payload = item[valueMember]; - return item; - }); + let menuItems = this.props.menuItems.map((item, idx) => + + ); + return (
- - -
- {displayValue} +
+
+ {displayValue} +
+ +
- -
- - - - {this.state.open &&
} -
+ + + {menuItems} + + +
); }, _setWidth() { let el = ReactDOM.findDOMNode(this); - let menuItemsDom = ReactDOM.findDOMNode(this.refs.menuItems); if (!this.props.style || !this.props.style.hasOwnProperty('width')) { el.style.width = 'auto'; - el.style.width = menuItemsDom.offsetWidth + 'px'; } }, @@ -278,9 +284,13 @@ const DropDownMenu = React.createClass({ this.setState({selectedIndex: (selectedIndex > -1) ? selectedIndex : 0}); }, - _onControlClick() { + _onControlClick(event) { + event.preventDefault(); if (!this.props.disabled) { - this.setState({open: !this.state.open}); + this.setState({ + open: !this.state.open, + anchorEl: ReactDOM.findDOMNode(this), + }); } }, @@ -316,19 +326,20 @@ const DropDownMenu = React.createClass({ e.preventDefault(); }, - _onMenuItemClick(e, key, payload) { - let selectedItem = this.props.menuItems[key]; - if (selectedItem) { - e.target.value = selectedItem[this.props.valueMember]; - } + _onMenuItemClick(key, payload, e) { + if (this.props.onChange && this.state.selectedIndex !== key || e.target.value !== this.props.value) { + let selectedItem = this.props.menuItems[key]; + if (selectedItem) { + e.target.value = selectedItem[this.props.valueMember]; + } - if (this.props.onChange && (this.state.selectedIndex !== key || e.target.value !== this.props.value)) { if (this.props.valueLink) { this.props.valueLink.requestChange(e.target.value); } else { this.props.onChange(e, key, payload); } + this._onMenuRequestClose(); } this.setState({ @@ -339,7 +350,10 @@ const DropDownMenu = React.createClass({ }, _onMenuRequestClose() { - this.setState({open:false}); + this.setState({ + open:false, + anchorEl:null, + }); }, _selectPreviousItem() { @@ -350,12 +364,6 @@ const DropDownMenu = React.createClass({ this.setState({selectedIndex: Math.min(this.state.selectedIndex + 1, this.props.menuItems.length - 1)}); }, - _handleOverlayTouchTap() { - this.setState({ - open: false, - }); - }, - _isControlled() { return this.props.hasOwnProperty('value') || this.props.hasOwnProperty('valueLink'); diff --git a/src/popover/popover-animate-from-top.jsx b/src/popover/popover-animate-from-top.jsx new file mode 100644 index 00000000000000..acf14a5c2774ec --- /dev/null +++ b/src/popover/popover-animate-from-top.jsx @@ -0,0 +1,114 @@ +import Transitions from '../styles/transitions'; +import React from 'react'; +import PropTypes from '../utils/prop-types'; +import StylePropable from '../mixins/style-propable'; +import DefaultRawTheme from '../styles/raw-themes/light-raw-theme'; +import ThemeManager from '../styles/theme-manager'; +import Paper from '../paper'; + +const PopoverAnimation = React.createClass({ + mixins: [StylePropable], + + propTypes: { + children: React.PropTypes.node, + className: React.PropTypes.string, + closing: React.PropTypes.bool, + open: React.PropTypes.bool.isRequired, + style: React.PropTypes.object, + targetOrigin: PropTypes.origin, + zDepth: PropTypes.zDepth, + }, + + getInitialState() { + return { + muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), + mounted: false, + }; + }, + + //for passing default theme context to children + childContextTypes: { + muiTheme: React.PropTypes.object, + }, + + getChildContext() { + return { + muiTheme: this.state.muiTheme, + }; + }, + + getDefaultProps() { + return { + style: {}, + zDepth: 1, + }; + }, + + componentWillMount() { + setTimeout(() => this.setState({mounted:true}), 0); + }, + + componentWillReceiveProps(nextProps, nextContext) { + let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; + + this.setState({ + mounted:nextProps.open && !nextProps.closing, + muiTheme:newMuiTheme, + }); + }, + + componentWillUnmount() { + this.setState({mounted:false}); + }, + + getStyles() { + let {targetOrigin} = this.props; + let horizontal = targetOrigin.horizontal.replace('middle', 'vertical'); + + return { + base: { + opacity:0, + transform:'scaleY(0)', + transformOrigin: `${horizontal} ${targetOrigin.vertical}`, + position: 'fixed', + zIndex: this.state.muiTheme.zIndex.popover, + transition: Transitions.easeOut('450ms', ['transform', 'opacity']), + maxHeight:'100%', + }, + + }; + }, + + getOpenStyles() { + return { + base: { + opacity: 1, + transform:'scaleY(1)', + }, + }; + }, + + render() { + let { + className, + style, + zDepth, + } = this.props; + + let styles = this.getStyles(); + let openStyles = {}; + if (this.state.mounted) + openStyles = this.getOpenStyles(); + + return ( + + {this.props.children} + + ); + }, +}); + +export default PopoverAnimation; diff --git a/src/select-field.jsx b/src/select-field.jsx index 86669742487888..519561362e4904 100644 --- a/src/select-field.jsx +++ b/src/select-field.jsx @@ -91,40 +91,41 @@ const SelectField = React.createClass({ getStyles() { let styles = { root: { - height: 46, position: 'relative', width: '100%', - top: 16, fontSize: 16, + height:48, + overflow:'hidden', + display:'block', }, label: { paddingLeft: 0, - top: 4, - width: '100%', + top: -4, }, icon: { - top: 20, right: 0, + top: 14, }, - underline: { + hideDropDownUnderline: { borderTop: 'none', }, - input: {}, + underline: { + bottom:8, + }, + input: { + verticalAlign:'top', + }, error: {}, + floatingLabel: {}, }; - if (!this.props.floatingLabelText) { - styles.label.top = -6; - styles.icon.top = 11; - - if (this.props.hintText) { - styles.root.top = -5; - } else { - styles.root.top = -8; - } - } else { - styles.error.bottom = -15; + if (this.props.floatingLabelText) { + styles.icon.top = 22; + styles.label.top = 8; } + else { + } + return styles; }, @@ -154,10 +155,11 @@ const SelectField = React.createClass({ const textFieldProps = { style: this.mergeAndPrefix(styles.input, style), floatingLabelText: floatingLabelText, - floatingLabelStyle: floatingLabelStyle, + floatingLabelStyle: this.mergeAndPrefix(styles.floatingLabel, floatingLabelStyle), hintText: (!hintText && !floatingLabelText) ? ' ' : hintText, fullWidth: fullWidth, errorText: errorText, + underlineStyle: this.mergeAndPrefix(styles.underline, underlineStyle), errorStyle: this.mergeAndPrefix(styles.error, errorStyle), onFocus: onFocus, onBlur: onBlur, @@ -168,11 +170,10 @@ const SelectField = React.createClass({ style: this.mergeAndPrefix(styles.root, selectFieldRoot), labelStyle: this.mergeAndPrefix(styles.label, labelStyle), iconStyle: this.mergeAndPrefix(styles.icon, iconStyle), - underlineStyle: this.mergeAndPrefix(styles.underline, underlineStyle), + underlineStyle: this.mergeAndPrefix(styles.hideDropDownUnderline), autoWidth: false, labelMember: labelMember, }; - return ( diff --git a/src/text-field.jsx b/src/text-field.jsx index 23b19d8a5b92e2..3962684746f9be 100644 --- a/src/text-field.jsx +++ b/src/text-field.jsx @@ -338,8 +338,9 @@ const TextField = React.createClass({ if (!this.props.hasOwnProperty('valueLink')) { inputProps.onChange = this._handleInputChange; } + if (this.props.children) { - let childInputStyle = this.mergeStyles(inputStyle, this.props.children.style); + let childInputStyle = this.mergeStyles(inputStyle, this.props.children.props.style); inputElement = React.cloneElement(this.props.children, {...inputProps, ...this.props.children.props, style:childInputStyle}); } else {