import React from 'react' import { keyframes } from '@emotion/core' import { Box } from '../Box' import { useThemeProps } from '../system' const rotate = keyframes({ '100%': { transform: 'rotate(360deg)' }, }) const rotateCentered = keyframes({ '100%': { transform: 'translate(-50%, -50%) rotate(360deg)' }, }) export type SpinnerProps = { /** * Uses position absolute and transforms to position in the center of a relative parent. */ center?: boolean /** * Primary color of spinner. */ color?: string /** * Size of spinner. */ size?: 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | number | string /** * Thickness of spinner. */ thickness?: number /** * Secondary color of spinner. */ trackColor?: string } export function Spinner({ center, size = 'md', thickness, ...props }: SpinnerProps) { const { color, sizes, thickness: sizeThickness, trackColor, ...restProps } = useThemeProps('spinner', props) const boxProps: any = { inline: true, alignSelf: 'center', verticalAlign: 'middle', radius: 'circle', borderColor: trackColor, borderTopColor: color, } const sizeValue = sizes[size] || size const thicknessValue = thickness || sizeThickness[size] const boxSizeStyles = { borderWidth: thicknessValue, height: sizeValue, width: sizeValue, } if (process.env.NODE_ENV !== 'production') { const width = typeof sizeValue === 'number' ? sizeValue * 8 : sizeValue.includes('px') ? parseInt(sizeValue) : null const spinnerRadius = width && width / 2 if (spinnerRadius && thicknessValue > spinnerRadius) console.warn( `The thickness value (${thicknessValue}px) of this spinner is larger than the radius (${spinnerRadius}px), this will distort the rendered size.` ) } if (center) { boxProps.position = 'absolute' boxProps.left = '50%' boxProps.top = '50%' boxProps.transform = 'translate(-50%, -50%) rotate(0deg)' boxProps.animation = `${rotateCentered} 500ms infinite linear` } else { boxProps.transform = 'rotate(0deg)' boxProps.animation = `${rotate} 500ms infinite linear` } return }