2018-07-06 18:56:28 -04:00
|
|
|
import React from 'react';
|
2018-08-27 10:23:21 -06:00
|
|
|
import PropTypes from 'prop-types';
|
2018-07-06 18:56:28 -04:00
|
|
|
import styled, { css, keyframes } from 'react-emotion';
|
|
|
|
import CSSTransition from 'react-transition-group/CSSTransition';
|
|
|
|
import { colors } from './styles';
|
|
|
|
|
|
|
|
const styles = {
|
|
|
|
disabled: css`
|
|
|
|
display: none;
|
|
|
|
`,
|
|
|
|
active: css`
|
|
|
|
display: block;
|
|
|
|
`,
|
|
|
|
enter: css`
|
|
|
|
opacity: 0.01;
|
|
|
|
`,
|
|
|
|
enterActive: css`
|
|
|
|
opacity: 1;
|
|
|
|
transition: opacity 500ms ease-in;
|
|
|
|
`,
|
|
|
|
exit: css`
|
|
|
|
opacity: 1;
|
|
|
|
`,
|
|
|
|
exitActive: css`
|
|
|
|
opacity: 0.01;
|
|
|
|
transition: opacity 300ms ease-in;
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
|
|
|
|
const animations = {
|
|
|
|
loader: keyframes`
|
|
|
|
from {
|
|
|
|
transform: rotate(0deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
to {
|
|
|
|
transform: rotate(360deg);
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
|
|
|
|
const LoaderText = styled.div`
|
|
|
|
width: auto !important;
|
|
|
|
height: auto !important;
|
|
|
|
text-align: center;
|
|
|
|
color: #767676;
|
|
|
|
margin-top: 55px;
|
|
|
|
line-height: 35px;
|
2018-08-07 14:46:54 -06:00
|
|
|
`;
|
2018-07-06 18:56:28 -04:00
|
|
|
|
|
|
|
const LoaderItem = styled.div`
|
|
|
|
position: absolute;
|
|
|
|
white-space: nowrap;
|
|
|
|
transform: translateX(-50%);
|
2018-08-07 14:46:54 -06:00
|
|
|
`;
|
2018-07-06 18:56:28 -04:00
|
|
|
|
|
|
|
export class Loader extends React.Component {
|
2018-08-27 10:23:21 -06:00
|
|
|
static propTypes = {
|
|
|
|
children: PropTypes.node,
|
|
|
|
className: PropTypes.string,
|
|
|
|
};
|
|
|
|
|
2018-07-06 18:56:28 -04:00
|
|
|
state = {
|
|
|
|
currentItem: 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
if (this.interval) {
|
|
|
|
clearInterval(this.interval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setAnimation = () => {
|
|
|
|
if (this.interval) return;
|
|
|
|
const { children } = this.props;
|
|
|
|
|
|
|
|
this.interval = setInterval(() => {
|
2018-08-07 14:46:54 -06:00
|
|
|
const nextItem =
|
|
|
|
this.state.currentItem === children.length - 1 ? 0 : this.state.currentItem + 1;
|
2018-07-06 18:56:28 -04:00
|
|
|
this.setState({ currentItem: nextItem });
|
|
|
|
}, 5000);
|
|
|
|
};
|
|
|
|
|
|
|
|
renderChild = () => {
|
|
|
|
const { children } = this.props;
|
|
|
|
const { currentItem } = this.state;
|
|
|
|
if (!children) {
|
|
|
|
return null;
|
|
|
|
} else if (typeof children == 'string') {
|
|
|
|
return <LoaderText>{children}</LoaderText>;
|
|
|
|
} else if (Array.isArray(children)) {
|
|
|
|
this.setAnimation();
|
|
|
|
return (
|
|
|
|
<LoaderText>
|
|
|
|
<CSSTransition
|
|
|
|
classNames={{
|
|
|
|
enter: styles.enter,
|
|
|
|
enterActive: styles.enterActive,
|
|
|
|
exit: styles.exit,
|
|
|
|
exitActive: styles.exitActive,
|
|
|
|
}}
|
|
|
|
timeout={500}
|
|
|
|
>
|
|
|
|
<LoaderItem key={currentItem}>{children[currentItem]}</LoaderItem>
|
|
|
|
</CSSTransition>
|
|
|
|
</LoaderText>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
2018-08-07 09:53:31 -06:00
|
|
|
const { className } = this.props;
|
2018-07-26 13:43:43 -04:00
|
|
|
return <div className={className}>{this.renderChild()}</div>;
|
2018-07-06 18:56:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const StyledLoader = styled(Loader)`
|
2018-08-07 14:46:54 -06:00
|
|
|
display: ${props => (props.active ? 'block' : 'none')};
|
2018-07-06 18:56:28 -04:00
|
|
|
position: absolute;
|
|
|
|
top: 50%;
|
|
|
|
left: 50%;
|
|
|
|
margin: 0px;
|
|
|
|
text-align: center;
|
|
|
|
z-index: 1000;
|
|
|
|
transform: translateX(-50%) translateY(-50%);
|
|
|
|
|
|
|
|
&:before,
|
|
|
|
&:after {
|
2018-07-26 13:43:43 -04:00
|
|
|
content: '';
|
|
|
|
position: absolute;
|
|
|
|
top: 0%;
|
|
|
|
left: 50%;
|
2018-07-06 18:56:28 -04:00
|
|
|
width: 2.28571429rem;
|
|
|
|
height: 2.28571429rem;
|
|
|
|
margin: 0em 0em 0em -1.14285714rem;
|
2018-07-26 13:43:43 -04:00
|
|
|
border-radius: 500rem;
|
|
|
|
border-style: solid;
|
|
|
|
border-width: 0.2em;
|
2018-07-06 18:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Static Shape */
|
|
|
|
&:before {
|
2018-07-26 13:43:43 -04:00
|
|
|
border-color: rgba(0, 0, 0, 0.1);
|
2018-07-06 18:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Active Shape */
|
|
|
|
&:after {
|
|
|
|
animation: ${animations.loader} 0.6s linear;
|
|
|
|
animation-iteration-count: infinite;
|
|
|
|
border-color: ${colors.active} transparent transparent;
|
|
|
|
box-shadow: 0px 0px 0px 1px transparent;
|
|
|
|
}
|
2018-08-07 14:46:54 -06:00
|
|
|
`;
|
2018-07-06 18:56:28 -04:00
|
|
|
|
|
|
|
export default StyledLoader;
|