UNPKG

wix-style-react

Version:
167 lines (149 loc) 4.11 kB
import React from 'react'; import PropTypes from 'prop-types'; import FormFieldError from 'wix-ui-icons-common/system/FormFieldError'; import FormFieldErrorSmall from 'wix-ui-icons-common/system/FormFieldErrorSmall'; import ToggleOn from 'wix-ui-icons-common/system/ToggleOn'; import CircleLoaderCheck from 'wix-ui-icons-common/system/CircleLoaderCheck'; import CircleLoaderCheckSmall from 'wix-ui-icons-common/system/CircleLoaderCheckSmall'; import Arc from './Arc'; import Heading from '../Heading'; import Tooltip from '../Tooltip'; import { st, classes } from './Loader.st.css'; const arcsAngles = { tiny: { light: 216, dark: 144, }, small: { light: 216, dark: 144, }, medium: { light: 108, dark: 108, }, large: { light: 180, dark: 180, }, }; const strokeWidths = { tiny: 3, small: 4, medium: 4, large: 4, }; const sizesInPx = { tiny: 18, small: 30, medium: 54, large: 102, }; const FULL_CIRCLE_ANGLE = 359; const sizeToSuccessIcon = { tiny: <ToggleOn />, small: <CircleLoaderCheckSmall />, medium: <CircleLoaderCheck />, large: <CircleLoaderCheck />, }; const sizeToErrorIcon = { tiny: <FormFieldError />, small: <FormFieldErrorSmall />, medium: <FormFieldError />, large: <FormFieldError />, }; class Loader extends React.PureComponent { static displayName = 'Loader'; static propTypes = { /** Applied as data-hook HTML attribute that can be used in the tests */ dataHook: PropTypes.string, /** The size of the loader */ size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large']), /** The color of the loader */ color: PropTypes.oneOf(['blue', 'white']), /** Node (usually text) to be shown below the loader */ text: PropTypes.node, /** The status of the loader */ status: PropTypes.oneOf(['loading', 'success', 'error']), /** Text to be shown in the tooltip **/ statusMessage: PropTypes.string, }; static defaultProps = { size: 'medium', color: 'blue', status: 'loading', }; render() { const { dataHook, size, color, text, status, statusMessage } = this.props; const sizeInPx = sizesInPx[size]; const shouldShowFullCircle = status !== 'loading'; const lightArcAngle = !shouldShowFullCircle ? arcsAngles[size].light : FULL_CIRCLE_ANGLE; const darkArcAngle = !shouldShowFullCircle ? arcsAngles[size].dark : FULL_CIRCLE_ANGLE; const shouldShowText = size !== 'tiny'; const successIcon = sizeToSuccessIcon[size]; const errorIcon = sizeToErrorIcon[size]; const strokeWidth = strokeWidths[size]; const loader = ( <div className={classes.arcsContainer} style={{ width: `${sizeInPx}px`, height: `${sizeInPx}px`, }} > <Arc angle={lightArcAngle} className={classes.lightArc} strokeWidth={strokeWidth} viewBoxSize={sizeInPx} /> <Arc angle={darkArcAngle} className={classes.darkArc} strokeWidth={strokeWidth} viewBoxSize={sizeInPx} /> {status !== 'loading' && ( <div className={classes.statusIndicator}> {status === 'success' && successIcon} {status === 'error' && errorIcon} </div> )} </div> ); return ( <div className={st(classes.root, { size, color, status })} data-hook={dataHook} data-size={size} data-color={color} data-status={status} > {statusMessage ? ( <Tooltip content={statusMessage} appendTo="window" dataHook="loader-tooltip" > {loader} </Tooltip> ) : ( loader )} {/* Footer Text */} {shouldShowText && text && ( <div className={classes.text}> <Heading appearance="H6" dataHook="loader-text"> {this.props.text} </Heading> </div> )} </div> ); } } export default Loader;