import React , { memo , forwardRef } from 'react' ; import { Animated , Platform } from 'react-native' ; import { usePropsResolution } from '../../../hooks' ; import { canUseDom } from '../../../utils' ; import Box from '../../primitives/Box' ; import type { ISkeletonProps } from './types' ; import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps' ; import { useToken } from '../../../hooks/useToken' ; const Skeleton = ( props , ref ) => { const isDomUsable = canUseDom ( ) ; const { children , startColor , endColor , ... resolvedProps } = usePropsResolution ( 'Skeleton' , props ) ; const blinkAnim = React . useRef ( new Animated . Value ( 0 ) ) . current ; const tokenisedStartColor = useToken ( 'colors' , startColor ) ; React . useEffect ( ( ) => { if ( isDomUsable ) { const blink = Animated . sequence ( [ Animated . timing ( blinkAnim , { toValue : 1 , duration : resolvedProps . fadeDuration * 10000 * ( 1 / resolvedProps . speed ) , useNativeDriver : Platform . OS !== 'web' , } ) , Animated . timing ( blinkAnim , { toValue : 0 , duration : resolvedProps . fadeDuration * 10000 * ( 1 / resolvedProps . speed ) , useNativeDriver : Platform . OS !== 'web' , } ) , ] ) ; Animated . loop ( blink ) . start ( ) ; } } , [ blinkAnim , isDomUsable , resolvedProps ] ) ; const skeletonStyle = { skeleton : { height : '100%' , width : '100%' , backgroundColor : tokenisedStartColor , opacity : blinkAnim , } , } ; if ( useHasResponsiveProps ( props ) ) { return null ; } return resolvedProps . isLoaded ? ( children ) : ( < Box bg = { endColor } { ... resolvedProps } ref = { ref } overflow = "hidden" > < Animated . View style = { skeletonStyle . skeleton } /> < /Box>); } ; export default memo ( forwardRef ( Skeleton ) ) ;