@smollweide/material-ui-speed-dial
Version:
Components, that implements material design speed dial for material-ui v1
164 lines (145 loc) • 3.81 kB
JavaScript
/* eslint complexity: 0*/
import React, { Component, Fragment } from 'react';
import { withStyles } from '@material-ui/core/styles';
import styles from './SpeedDial.styles';
const STATE = {
CLOSED: 'closed',
OPENING: 'opening',
OPENED: 'opened',
CLOSING: 'closing'
};
export class SpeedDial extends Component {
constructor(props) {
super(props);
this.handleOpen = () => {
if (!this.isControlled) {
this.open();
}
};
this.handleClose = () => {
if (!this.isControlled) {
this.close();
}
};
this.state = {
state: this.isControlled && props.isOpen ? STATE.OPENED : STATE.CLOSED
};
}
componentDidMount() {
this.forceSetState = this.setState;
}
componentWillReceiveProps(nextProps) {
if (!this.isControlled) {
return;
}
if (!this.props.isOpen && nextProps.isOpen) {
this.open();
return;
}
if (this.props.isOpen && !nextProps.isOpen) {
this.close();
return;
}
}
componentWillUnmount() {
/* istanbul ignore next */
this.forceSetState = () => {};
}
get isControlled() {
return typeof this.props.isOpen === 'boolean';
}
close() {
this.forceSetState({ state: STATE.CLOSING }, () => {
setTimeout(() => {
this.forceSetState({ state: STATE.CLOSED });
}, this.props.animationDelay);
});
}
open() {
this.forceSetState({ state: STATE.OPENING }, () => {
setTimeout(() => {
this.forceSetState({ state: STATE.OPENED });
}, this.props.animationDelay);
});
}
renderButton() {
const { classes, preset, renderButton, renderOpenedButton } = this.props;
const { state } = this.state;
if (!renderOpenedButton) {
return renderButton({
className: `${classes.button} ${preset.button}`,
onClick: state === STATE.OPENED ? this.handleClose : this.handleOpen,
state
}, {
className: `${classes.buttonIcon} ${classes.buttonIconSingle} ${classes[`buttonIconSingle--state-${state}`]}`,
state
});
}
return [renderButton({
key: 'closed',
className: `${classes.button} ${classes.buttonClosed} ${classes[`buttonClosed--state-${state}`]} ${preset.button}`,
onClick: this.handleOpen,
state
}, {
className: `${classes.buttonIcon} ${classes.buttonClosedIcon} ${classes[`buttonClosedIcon--state-${state}`]}`,
state
}), renderOpenedButton({
key: 'open',
className: `${classes.button} ${classes.buttonOpened} ${classes[`buttonOpened--state-${state}`]} ${preset.button}`,
onClick: this.handleClose,
state
}, {
className: `${classes.buttonIcon} ${classes.buttonOpenedIcon} ${classes[`buttonOpenedIcon--state-${state}`]}`,
state
})];
}
render() {
const { classes, preset, className, renderList, renderBackdrop, renderOuterRimButton, children } = this.props;
const { state } = this.state;
return React.createElement(
Fragment,
null,
renderBackdrop && renderBackdrop({
className: `${preset.backdrop}`,
state,
onClick: this.handleClose
}),
React.createElement(
'div',
{ className: `${preset.root} ${className || ''}` },
renderOuterRimButton && renderOuterRimButton({
className: `${classes.button} ${classes.buttonOuterRim} ${classes[`buttonOuterRim--state-${state}`]} ${preset.buttonOuterRim}`,
state
}, {
className: '',
state
}),
renderList({
className: `${classes.list} ${classes[`list--state-${state}`]} ${preset.list}`,
children: children({
state,
preset,
className: `${preset.item}`,
handleClose: this.handleClose
}),
state
}),
this.renderButton()
)
);
}
}
SpeedDial.displayName = 'SpeedDial';
SpeedDial.defaultProps = {
animationDelay: 500,
preset: {
root: '',
button: '',
list: '',
item: '',
firstItem: '',
avatar: '',
label: ''
}
};
export default withStyles(styles)(SpeedDial);