import { FunctionComponent } from 'react' ; import styled , { keyframes } from 'styled-components' ; type Props = { isLoading : boolean ; nRows ? : number ; lineSpacing ? : number ; maxWidth ? : string ; } ; const getGradient = ( theme ) => { const bgColor = theme . colors . smoke . base ; const highlightColor = 'rgba(255, 255, 255, 0.6)' ; return `${ bgColor } linear-gradient(to right, ${ bgColor }, ${ highlightColor } 70%, ${ bgColor })` ; } ; const backgroundAnimation = keyframes `
  from {
    background-position: 0 0;
  }

  // This 70% keyframe is so the animation eases quite aggressively
  70% {
    background-position: -50% 0;
  }

  // This is a "complete rotation" of the background - ie back to the start
  to {
    background-position: -200% 0;
  }
` ; const PlaceholderRow = styled . div < { lineSpacing : number ; percentWidth : number ; } > `
  background: ${ ( { theme } ) => getGradient ( theme ) };

  // This "stretches" the periodic background so we only see half of it
  background-size: 200%;
  background-repeat: repeat-x;
  animation: ${ backgroundAnimation } 1.2s ease-in infinite;
  width: ${ ( { percentWidth } ) => percentWidth . toFixed ( 2 ) }%;

  // These should sum to 1.5rem to reflect the usual line-height of inline text
  height: 1rem;
  margin-top: 0.5rem;
` ; const Wrapper = styled . div < { maxWidth : string ; } > `
  max-width: ${ ( { maxWidth } ) => maxWidth };
` ; const widthOffsets = [ 0.8 , 0.6 , 0.3 , 0.5 , 0.8 , 0.5 , 0.2 , 0.4 , 0.3 , 0.1 ] ; const randomWidth = ( { min , i } ) => 100 - ( 100 - min ) * widthOffsets [ i % widthOffsets . length ] ; const Placeholder = ( { children , isLoading , maxWidth , nRows , lineSpacing , } ) => { if ( isLoading ) { return ( < Wrapper maxWidth = { maxWidth || '100%' } > { Array . from ( { length : nRows || 1 } ) . map ( ( _ , i ) => ( < PlaceholderRow key = { `row-${ i }` } lineSpacing = { lineSpacing ?? 0.5 } percentWidth = { randomWidth ( { min : 95 , i } ) } / > ) ) } < /Wrapper>); } return < > { children } < />; } ; export default Placeholder ;