d2-ui
Version:
257 lines (221 loc) • 6.57 kB
JSX
import React from 'react';
import EnhancedSwitch from './enhanced-switch';
import StylePropable from './mixins/style-propable';
import Transitions from './styles/transitions';
import CheckboxOutline from './svg-icons/toggle/check-box-outline-blank';
import CheckboxChecked from './svg-icons/toggle/check-box';
import getMuiTheme from './styles/getMuiTheme';
const Checkbox = React.createClass({
propTypes: {
/**
* Checkbox is checked if true.
*/
checked: React.PropTypes.bool,
/**
* The SvgIcon to use for the checked state.
* This is useful to create icon toggles.
*/
checkedIcon: React.PropTypes.element,
/**
* The default state of our checkbox component.
*/
defaultChecked: React.PropTypes.bool,
/**
* Disabled if true.
*/
disabled: React.PropTypes.bool,
/**
* Overrides the inline-styles of the icon element.
*/
iconStyle: React.PropTypes.object,
/**
* Where the label will be placed next to the checkbox.
*/
labelPosition: React.PropTypes.oneOf(['left', 'right']),
/**
* Overrides the inline-styles of the Checkbox element label.
*/
labelStyle: React.PropTypes.object,
/**
* Callback function that is fired when the checkbox is checked.
*/
onCheck: React.PropTypes.func,
/**
* Override the inline-styles of the root element.
*/
style: React.PropTypes.object,
/**
* The SvgIcon to use for the unchecked state.
* This is useful to create icon toggles.
*/
unCheckedIcon: React.PropTypes.element,
/**
* ValueLink for when using controlled checkbox.
*/
valueLink: React.PropTypes.object,
},
contextTypes: {
muiTheme: React.PropTypes.object,
},
//for passing default theme context to children
childContextTypes: {
muiTheme: React.PropTypes.object,
},
mixins: [StylePropable],
getDefaultProps() {
return {
defaultChecked: false,
labelPosition: 'right',
disabled: false,
};
},
getInitialState() {
return {
switched:
this.props.checked ||
this.props.defaultChecked ||
(this.props.valueLink && this.props.valueLink.value) ||
false,
muiTheme: this.context.muiTheme || getMuiTheme(),
};
},
getChildContext() {
return {
muiTheme: this.state.muiTheme,
};
},
//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,
switched: this.props.checked !== nextProps.checked
? nextProps.checked
: this.state.switched,
});
},
getTheme() {
return this.state.muiTheme.checkbox;
},
getStyles() {
let checkboxSize = 24;
let styles = {
icon: {
height: checkboxSize,
width: checkboxSize,
},
check: {
position: 'absolute',
opacity: 0,
transform: 'scale(0)',
transitionOrigin: '50% 50%',
transition: Transitions.easeOut('450ms', 'opacity', '0ms') + ', ' +
Transitions.easeOut('0ms', 'transform', '450ms'),
fill: this.getTheme().checkedColor,
},
box: {
position: 'absolute',
opacity: 1,
fill: this.getTheme().boxColor,
transition: Transitions.easeOut('2s', null, '200ms'),
},
checkWhenSwitched: {
opacity: 1,
transform: 'scale(1)',
transition: Transitions.easeOut('0ms', 'opacity', '0ms') + ', ' +
Transitions.easeOut('800ms', 'transform', '0ms'),
},
boxWhenSwitched: {
transition: Transitions.easeOut('100ms', null, '0ms'),
fill: this.getTheme().checkedColor,
},
checkWhenDisabled: {
fill: this.getTheme().disabledColor,
},
boxWhenDisabled: {
fill: this.getTheme().disabledColor,
},
label: {
color: this.props.disabled ? this.getTheme().labelDisabledColor : this.getTheme().labelColor,
},
};
return styles;
},
isChecked() {
return this.refs.enhancedSwitch.isSwitched();
},
setChecked(newCheckedValue) {
this.refs.enhancedSwitch.setSwitched(newCheckedValue);
},
_handleCheck(e, isInputChecked) {
if (this.props.onCheck) this.props.onCheck(e, isInputChecked);
},
_handleStateChange(newSwitched) {
this.setState({switched: newSwitched});
},
render() {
let {
iconStyle,
onCheck,
checkedIcon,
unCheckedIcon,
...other,
} = this.props;
let styles = this.getStyles();
let boxStyles =
this.mergeStyles(
styles.box,
this.state.switched && styles.boxWhenSwitched,
iconStyle,
this.props.disabled && styles.boxWhenDisabled);
let checkStyles =
this.mergeStyles(
styles.check,
this.state.switched && styles.checkWhenSwitched,
iconStyle,
this.props.disabled && styles.checkWhenDisabled);
let checkedElement = checkedIcon ? React.cloneElement(checkedIcon, {
style: this.mergeStyles(checkStyles, checkedIcon.props.style),
}) : React.createElement(CheckboxChecked, {
style: checkStyles,
});
let unCheckedElement = unCheckedIcon ? React.cloneElement(unCheckedIcon, {
style: this.mergeStyles(boxStyles, unCheckedIcon.props.style),
}) : React.createElement(CheckboxOutline, {
style: boxStyles,
});
let checkboxElement = (
<div>
{unCheckedElement}
{checkedElement}
</div>
);
let rippleColor = this.state.switched ? checkStyles.fill : boxStyles.fill;
let mergedIconStyle = this.mergeStyles(styles.icon, iconStyle);
let labelStyle = this.mergeStyles(
styles.label,
this.props.labelStyle
);
let enhancedSwitchProps = {
ref: 'enhancedSwitch',
inputType: 'checkbox',
switched: this.state.switched,
switchElement: checkboxElement,
rippleColor: rippleColor,
iconStyle: mergedIconStyle,
onSwitch: this._handleCheck,
labelStyle: labelStyle,
onParentShouldUpdate: this._handleStateChange,
defaultSwitched: this.props.defaultChecked,
labelPosition: this.props.labelPosition,
};
return (
<EnhancedSwitch
{...other}
{...enhancedSwitchProps}
/>
);
},
});
export default Checkbox;