Skip to content

Commit

Permalink
dropdown using new popover
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismcv committed Dec 4, 2015
1 parent 1741f62 commit 84614f0
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 83 deletions.
130 changes: 69 additions & 61 deletions src/drop-down-menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({

Expand Down Expand Up @@ -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(),
Expand All @@ -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 +
Expand All @@ -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),
},
};

Expand Down Expand Up @@ -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) =>
<MenuItem
key={idx}
primaryText={item[displayMember]}
value={item[valueMember]}
onClick={this._onMenuItemClick.bind(this, idx, item[valueMember])} />
);


return (
<div
Expand All @@ -234,37 +237,40 @@ const DropDownMenu = React.createClass({
this.state.open && styles.rootWhenOpen,
style)} >

<ClearFix style={this.mergeStyles(styles.control)} onTouchTap={this._onControlClick}>
<Paper style={this.mergeStyles(styles.controlBg)} zDepth={0} />
<div style={this.prepareStyles(styles.label, this.state.open && styles.labelWhenOpen, labelStyle)}>
{displayValue}
<div style={this.mergeStyles(styles.control)} onTouchTap={this._onControlClick}>
<div style={this.prepareStyles(styles.label, this.state.open && styles.labelWhenOpen, labelStyle)}>
{displayValue}
</div>
<DropDownArrow style={this.mergeStyles(styles.icon, iconStyle)}/>
<div style={this.prepareStyles(styles.underline, underlineStyle)}/>
</div>
<DropDownArrow style={this.mergeStyles(styles.icon, iconStyle)}/>
<div style={this.prepareStyles(styles.underline, underlineStyle)}/>
</ClearFix>

<Menu
ref="menuItems"
autoWidth={autoWidth}
selectedIndex={selectedIndex}
menuItems={menuItems}
style={styles.menu}
menuItemStyle={this.mergeStyles(styles.menuItem, menuItemStyle)}
hideable={true}
visible={this.state.open}
onRequestClose={this._onMenuRequestClose}
onItemTap={this._onMenuItemClick} />
{this.state.open && <div style={this.prepareStyles(styles.overlay)} onTouchTap={this._handleOverlayTouchTap} />}
</div>
<Popover
anchorOrigin={{horizontal:'left', vertical:'top'}}
anchorEl={this.state.anchorEl}
animation={AnimateFromTop}
open={this.state.open}
onRequestClose={this._onMenuRequestClose} >
<Menu
ref="menuItems"
autoWidth={this.props.autoWidth}
desktop={true}
selectedIndex={selectedIndex}
style={styles.menu}
menuItemStyle={this.mergeStyles(styles.menuItem, this.props.menuItemStyle)}
hideable={true}
onRequestClose={this._onMenuRequestClose}
>
{menuItems}
</Menu>
</Popover>
</div>
);
},

_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';
}
},

Expand All @@ -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),
});
}
},

Expand Down Expand Up @@ -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({
Expand All @@ -339,7 +350,10 @@ const DropDownMenu = React.createClass({
},

_onMenuRequestClose() {
this.setState({open:false});
this.setState({
open:false,
anchorEl:null,
});
},

_selectPreviousItem() {
Expand All @@ -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');
Expand Down
114 changes: 114 additions & 0 deletions src/popover/popover-animate-from-top.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<Paper
style={this.mergeAndPrefix(styles.base, style, openStyles.base)}
zDepth={zDepth}
className={className}>
{this.props.children}
</Paper>
);
},
});

export default PopoverAnimation;
Loading

0 comments on commit 84614f0

Please sign in to comment.