(isAnimating: boolean)
| 30 | import {useMediaQuery} from './useMediaQuery'; |
| 31 | |
| 32 | export function useLoadingAnimation(isAnimating: boolean): (element: HTMLElement | null) => void { |
| 33 | let animationRef = useRef<Animation | null>(null); |
| 34 | let reduceMotion = useMediaQuery('(prefers-reduced-motion: reduce)'); |
| 35 | return useCallback( |
| 36 | (element: HTMLElement | null) => { |
| 37 | if ( |
| 38 | isAnimating && |
| 39 | !animationRef.current && |
| 40 | element && |
| 41 | !reduceMotion && |
| 42 | typeof element.animate === 'function' |
| 43 | ) { |
| 44 | // Use web animation API instead of CSS animations so that we can |
| 45 | // synchronize it between all loading elements on the page (via startTime). |
| 46 | animationRef.current = element.animate( |
| 47 | [{backgroundPosition: '100%'}, {backgroundPosition: '0%'}], |
| 48 | { |
| 49 | duration: 2000, |
| 50 | iterations: Infinity, |
| 51 | easing: 'ease-in-out' |
| 52 | } |
| 53 | ); |
| 54 | animationRef.current.startTime = 0; |
| 55 | } else if (!isAnimating && animationRef.current) { |
| 56 | animationRef.current.cancel(); |
| 57 | animationRef.current = null; |
| 58 | } |
| 59 | }, |
| 60 | [isAnimating, reduceMotion] |
| 61 | ); |
| 62 | } |
| 63 | |
| 64 | export type SkeletonElement = ReactElement<{ |
| 65 | children: ReactNode; |
no test coverage detected