react-sprucebot
Version:
React components for your Sprucebot Skill 💪🏼
226 lines (204 loc) • 4.34 kB
JavaScript
import React, { Component } from 'react'
import styled from 'styled-components'
import PropTypes from 'prop-types'
import Loader from '../Loader/Loader'
const ButtonWrapper = styled.div`
display: flex;
width: 50%;
${props => props.left && `padding-right: 1.125em;`};
${props => props.right && `padding-left: 1.125em;`};
`
const StyledButton = styled.button`
${props =>
props.busy ||
(props.disabled &&
`
pointer-events: none;
cursor: not-allowed;
`)};
`
const StyledAnchor = styled.a`
${props =>
props.busy ||
(props.disabled &&
`
pointer-events: none;
cursor: not-allowed;
`)};
`
// TODO refactor into styled component
export default class Button extends Component {
constructor(props) {
super(props)
this.state = {
busy: !!props.busy
}
}
componentWillReceiveProps(nextProps) {
if (typeof nextProps.busy !== 'undefined') {
this.setState({
busy: nextProps.busy
})
}
}
onClick = e => {
const { busy } = this.state
const { disabled, onClick, href, target, router } = this.props
if (busy || disabled) {
return
}
if (onClick) {
onClick(e)
} else if (href) {
e.preventDefault()
this.setState({ busy: true })
const url = href
if (/^http/.test(url)) {
// If the href is a full domain name
if (target) {
window.open(url, target)
} else {
window.open(url, '_self')
}
} else {
// Relative url
if (target) {
window.open(url, target)
} else if (router) {
router.push(url)
} else {
window.open(url, '_self')
}
}
// Reset the state to not-busy if it's been 10 sec
// is there a reason for this?
setTimeout(() => {
this.setState({ busy: false })
}, 10000)
}
}
renderView = () => {
const { busy } = this.state
const { hideLoader, loaderDark, loaderStyle, children } = this.props
if (busy && !hideLoader) {
return (
<Loader
dark={loaderDark ? true : false}
fullWidth={false}
loaderStyle={loaderStyle}
/>
)
}
return children
}
render() {
const {
tag,
disabled,
primary,
secondary,
alt,
link,
caution,
className,
children,
submit,
remove,
toggle,
router,
loaderDark,
loaderStyle,
busy: propBusy,
hideLoader,
tertiary,
left,
right,
...props
} = this.props
const { busy } = this.state
if (primary && secondary) {
return (
<button className="btn__primary">
'primary' and 'secondary' are mutually exclusive.
</button>
)
} else if (primary && alt) {
return (
<button className="btn__primary">
'primary' and 'alt' are mutually exclusive.
</button>
)
}
let btnClass = primary ? 'btn__primary' : ''
btnClass += secondary ? 'btn__secondary' : ''
btnClass += alt && btnClass.length > 0 ? '__alt' : ''
btnClass += alt && btnClass.length === 0 ? 'btn__alt' : ''
btnClass += disabled ? ' btn__disabled' : ''
btnClass += caution ? ' btn__caution' : ''
btnClass += link ? ' btn__link' : ''
btnClass += toggle ? 'btn__toggle' : ''
if (remove) {
btnClass = 'btn__remove'
}
// if this button has a href or is a "remove" button, make it an anchor
let Tag
if (props.href || remove) {
Tag = StyledAnchor
} else if (tag === 'button') {
Tag = StyledButton
} else {
Tag = tag
}
if (tertiary) {
return (
<ButtonWrapper left={left} right={right}>
<Tag
className={`btn ${btnClass} ${className || ''}`}
onClick={this.onClick}
disabled={disabled}
busy={busy}
{...props}
>
{this.renderView()}
</Tag>
</ButtonWrapper>
)
}
return (
<Tag
className={`${btnClass} ${className || ''}`}
onClick={this.onClick}
disabled={disabled}
busy={busy}
{...props}
>
{this.renderView()}
</Tag>
)
}
}
Button.propTypes = {
tag: PropTypes.string,
primary: PropTypes.bool,
alt: PropTypes.bool,
secondary: PropTypes.bool,
busy: PropTypes.bool,
href: PropTypes.string,
remove: PropTypes.bool,
toggle: PropTypes.bool,
hideLoader: PropTypes.bool,
tertiary: PropTypes.bool,
left: PropTypes.bool,
right: PropTypes.bool,
type: PropTypes.string
}
Button.defaultProps = {
tag: 'button',
primary: false,
alt: false,
secondary: false,
busy: false,
remove: false,
toggle: false,
type: 'button'
}