import styled , { css , keyframes } from 'styled-components' ; import { Directions } from 'src/components/core/enums' ; import { useCallback , useMemo , useState } from 'react' ; const verticalOffset = [ 0 , 130 , 260 ] ; const horizontalOffset = [ 0 , 90 , 180 ] ; function shuffle ( array ) { return array . sort ( ( ) => 0.5 - Math . random ( ) ) ; } function getImagePositions ( nftUrls ) { const shuffledVerticalOffset = shuffle ( verticalOffset ) ; const shuffledHorizontalOffset = shuffle ( horizontalOffset ) ; return nftUrls . map ( ( url , index ) => ( { top : shuffledVerticalOffset [ index ] + Math . random ( ) * 40 , left : shuffledHorizontalOffset [ index ] + Math . random ( ) * 40 , } ) ) ; } function getAnimationMovement ( ) { return { x : Math . random ( ) * 10 * ( Math . random ( ) > 0.5 ? 1 : - 1 ) , y : Math . random ( ) * 10 * ( Math . random ( ) > 0.5 ? 1 : - 1 ) , time : Math . random ( ) * 2 + 6 , } ; } function getFormattedImageUrl ( url ) { if ( ! url . includes ( 'googleusercontent' ) ) { return url ; } if ( url . includes ( '=s250' ) ) { return url . replace ( '=s250' , '=w250' ) ; } return `${ url }=w250` ; } type PreviewImageProps = { src : string ; top : number ; left : number ; movement : { x : number ; y : number ; time : number ; } ; } ; function PreviewImage ( { src , top , left , movement } ) { const [ isLoaded , setIsLoaded ] = useState ( false ) ; const onLoad = useCallback ( ( ) => { setIsLoaded ( true ) ; } , [ ] ) ; return ( < StyledPreviewImage src = { getFormattedImageUrl ( src ) } top = { top } left = { left } movement = { movement } onLoad = { onLoad } isLoaded = { isLoaded } / > ) ; } type MemberListGalleryPreviewProps = { direction : Directions . LEFT | Directions . RIGHT ; nftUrls : string [ ] ; startFadeOut ? : boolean ; } ; function MemberListGalleryPreview ( { direction , nftUrls , startFadeOut , } ) { const animationMovements = useMemo ( ( ) => nftUrls . map ( ( ) => getAnimationMovement ( ) ) , [ nftUrls ] ) ; const imagePositions = useMemo ( ( ) => getImagePositions ( nftUrls ) , [ nftUrls ] ) ; return ( < StyledPreview > < StyledPreviewImageWrapper direction = { direction } startFadeOut = { startFadeOut } > { nftUrls . map ( ( url , index ) => ( < PreviewImage key = { url } src = { url } top = { imagePositions [ index ] . top } left = { imagePositions [ index ] . left } movement = { animationMovements [ index ] } / > ) ) } < /StyledPreviewImageWrapper> < /StyledPreview>); } const StyledPreview = styled . div `
  position: relative;
` ; const fadeOut = keyframes `
  from { opacity: 1; };
  to { opacity: 0; };
` ; type StyledPreviewImageWrapperProps = { direction : Directions . LEFT | Directions . RIGHT ; startFadeOut ? : boolean ; } ; const StyledPreviewImageWrapper = styled . div < StyledPreviewImageWrapperProps > `
  position: absolute;
  top: -250px;
  left: ${ ( { direction } ) => ( direction === Directions . RIGHT ? '50px' : '-600px' ) };

  ${ ( { startFadeOut } ) => startFadeOut && css `
      animation: ${ fadeOut } 0.5s forwards;
    ` }
` ; const float = ( x , y ) => keyframes `
  0% {
    transform: translate(0px, 0px);
  }

  50% {
    transform: translate(${ x }px, ${ y }px);
  }

  100% {
    transform: translate(0px, 0px);
  }
` ; const fadeIn = keyframes `
  from { opacity: 0; };
  to { opacity: 1; };
` ; type Movement = { x : number ; y : number ; time : number ; } ; type StyledPreviewImageProps = { top : number ; left : number ; movement : Movement ; isLoaded : boolean ; } ; const StyledPreviewImage = styled . img < StyledPreviewImageProps > `
  position: absolute;
  top: ${ ( { top } ) => top }px;
  left: ${ ( { left } ) => left }px;
  background-color: white;
  width: 250px;
  opacity: 0;
  box-shadow: rgba(0, 0, 0, 0.2) 0px 18px 50px -10px;

  ${ ( { isLoaded , movement } ) => isLoaded && css `
      animation: ${ float ( movement . x , movement . y ) } ${ movement . time }s ease-in-out infinite,
        ${ fadeIn } 0.5s forwards;
    ` }
` ; export default MemberListGalleryPreview ;