license import React from 'react' ; import { Animated , StyleSheet , View , ViewProps , ViewStyle , } from 'react-native' ; import { EvaSize , EvaStatus , Size , Overwrite , LiteralUnion , } from '../../devsupport' ; import { styled , StyledComponentProps , } from '../../theme' ; import { SpinnerAnimation , SpinnerAnimationStyle , } from './animation' ; type SpinnerStyledProps = Overwrite < StyledComponentProps , { appearance ? : LiteralUnion < 'default' > ; } > ; export interface SpinnerProps extends ViewProps , SpinnerStyledProps { animating ? : boolean ; status ? : EvaStatus ; size ? : EvaSize ; } export type SpinnerElement = React . ReactElement < SpinnerProps > ; interface ArcElementStyle { container : ViewStyle ; arc : ViewStyle ; overflow ? : ViewStyle ; } extends React . Component property property property overview-example overview-example overview-example overview-example example @ styled ( 'Spinner' ) export class Spinner extends React . PureComponent < SpinnerProps > { static defaultProps : Partial < SpinnerProps > = { animating : true , } ; private animation : SpinnerAnimation = new SpinnerAnimation ( this . containerSize . height ) ; private get containerSize ( ) : Size { const { width , height } = StyleSheet . flatten ( [ this . props . eva . style , this . props . style ] ) ; return new Size ( width , height ) ; } public componentDidMount ( ) { if ( this . props . animating ) { this . startAnimation ( ) ; } } public componentDidUpdate ( prevProps ) { const animatingChanged = this . props . animating !== prevProps . animating ; if ( animatingChanged && this . props . animating ) { this . startAnimation ( ) ; } if ( animatingChanged && ! this . props . animating ) { this . stopAnimation ( ) ; } } public componentWillUnmount ( ) { this . animation . release ( ) ; } private startAnimation = ( ) : void => { this . animation . start ( ) ; } ; private stopAnimation = ( ) : void => { this . animation . stop ( ) ; } ; private getComponentStyle = ( source ) => { const start = { container : source . container , arc : source . start , } ; const end = { container : source . container , arc : source . end , overflow : { top : this . containerSize . height / 2 } , } ; return { start , end } ; } ; private renderArcElement = ( style , size ) : React . ReactElement < ViewProps > => { const arcSize = new Size ( size . width , size . height / 2 ) ; return ( < Animated . View style = { [ StyleSheet . absoluteFill , style . container , size ] } > < View style = { [ styles . noOverflow , style . overflow , arcSize ] } > < Animated . View style = { [ style . arc , size ] } > < View style = { [ styles . noOverflow , arcSize ] } > < View style = { [ this . props . eva . style , this . props . style ] } /> < /View> < /Animated.View> < /View> < /Animated.View>); } ; public render ( ) { const containerSize = this . containerSize ; const evaStyle = this . getComponentStyle ( this . animation . toProps ( ) ) ; return ( < View testID = { this . props . testID } style = { containerSize } > { this . renderArcElement ( evaStyle . start , containerSize ) } { this . renderArcElement ( evaStyle . end , containerSize ) } < /View>); } } const styles = StyleSheet . create ( { noOverflow : { overflow : 'hidden' , } , } ) ;