moq-ui
Version:
Simple, customizable UI components built with React
192 lines (165 loc) • 4.53 kB
JSX
/**
* @jsx React.DOM
*/
var React = require('react');
var Colors = require('./styles/colors');
var ColorManipulator = require('./utils/color-manipulator');
var StylePropable = require('./mixins/style-propable');
var ThemeManager = require('./styles/theme-manager');
var Transitions = require('./styles/transitions');
var Button = React.createClass({
mixins: [StylePropable],
contextTypes: {
uiTheme: React.PropTypes.object
},
propTypes: {
active: React.PropTypes.bool,
disabled: React.PropTypes.bool,
hidden: React.PropTypes.bool,
invisible: React.PropTypes.bool,
label: function(props, propName, componentName){
if (!props.children && !props.label) {
return new Error('Required prop `label` or `children` was not specified in `'+ componentName + '`.')
}
},
linkButton: React.PropTypes.bool,
primary: React.PropTypes.bool,
labelStyle: React.PropTypes.object
},
getDefaultProps: function() {
return {
type: "button"
}
},
getInitialState: function() {
return {
hovered: false,
};
},
getTheme: function() {
if (this.uiTheme === undefined) {
this.uiTheme = this.context.uiTheme || new ThemeManager().getCurrentTheme()
}
return this.uiTheme;
},
getThemeButton: function() {
return this.getTheme().component.button;
},
getStyles: function() {
var styles = {
core: {
// structural
display: 'inline-block',
lineHeight: 'normal',
whiteSpace: 'nowrap',
verticalAlign: 'middle',
textAlign: 'center',
cursor: 'pointer',
userDrag: 'none',
userSelect: 'none',
boxSizing: 'border-box',
zoom: 1,
// shared visual
transition: Transitions.easeOut(),
fontFamily: this.getTheme().fontFamily
},
// the `look an feel`
theme: this.getThemeButton(),
// properties
active: {
boxShadow: '0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset'
},
linkButton: {
textDecoration: 'none'
},
disabled: {
cursor: (this.props.disabled) ? 'not-allowed' : 'pointer',
opacity: 0.40,
boxShadow: 'none'
},
label: {
position: 'relative',
padding: '0 0',
},
primary: {
backgroundColor: this.getTheme().palette.primaryColor,
color: 'white'
}
};
return styles;
},
getClasses: function() {
var classString = 'moq-button';
if (this.props.className && this.props.className.length) {
classString += ' ' + this.props.className;
}
return classString;
},
render: function() {
var {
className,
active,
hidden,
invisible,
label,
linkButton,
primary,
onMouseOver,
onMouseOut,
...other
} = this.props;
var styles = this.mergeAndPrefix(
this.getStyles().core,
this.getStyles().theme,
this.props.active && this.getStyles().active,
this.props.disabled && this.getStyles().disabled,
this.props.linkButton && this.getStyles().linkButton,
this.props.primary && this.getStyles().primary,
this.props.style
);
if (this.props.hidden) {
styles.display = 'none';
}
if (this.props.invisible) {
styles.visibility = 'hidden';
}
// Simulate the ':hover' effect
if (this.state.hovered && !this.props.disabled) {
styles.backgroundColor = ColorManipulator.darken(styles.backgroundColor, 0.05);
}
var labelElement;
if (label) {
labelElement = (
<span style={this.mergeAndPrefix(this.getStyles().label, this.props.labelStyle)}>
{label}
</span>
);
}
var buttonProps = {
className: this.getClasses(),
style: styles,
onMouseOver: this._handleMouseOver,
onMouseOut: this._handleMouseOut
};
return linkButton ? (
<a {...other} {...buttonProps}>
{labelElement}
{this.props.children}
</a>
) : (
<button {...other} {...buttonProps}>
{labelElement}
{this.props.children}
</button>
);
},
_handleMouseOver: function(e) {
this.setState({hovered: true});
if (this.props.onMouseOver) this.props.onMouseOver(e);
},
_handleMouseOut: function(e) {
this.setState({hovered: false});
if (this.props.onMouseOut) this.props.onMouseOut(e);
},
});
module.exports = Button;