import { Fragment , Component , createRef , ReactNode } from 'react' ; import debounce from 'lodash.debounce' ; import { convertImageUri } from '../../../utils/convert-image-uri' ; import { classNames } from '../../../utils/classnames' ; import { imageSizes } from '../../../utils/image-sizes' ; import Tasl from '../Tasl/Tasl' ; import { ImageType } from '../../../model/image' ; import { CaptionedImage as CaptionedImageType } from '../../../model/captioned-image' ; import Caption from '../Caption/Caption' ; import LL from '../styled/LL' ; import styled from 'styled-components' ; type CaptionedImageProps = { isBody ? : boolean ; } ; const CaptionedImageFigure = styled . div < CaptionedImageProps > `
  margin: 0;
  display: inline-block;
  width: 100%;
  text-align: center;

  .image {
    max-height: 80vh;
    max-width: 100%;

  }

  noscript .image {
    max-height: none;
  }

  ${ props => props . isBody && `
    text-align: left;

    .caption {
      margin-left: 0;
      margin-right: 0;
    }
  ` }
}` ; export type UiImageProps = ImageType & { sizesQueries : string ; extraClasses ? : string ; isFull ? : boolean ; showTasl ? : boolean ; isWidthAuto ? : boolean ; setComputedImageWidth ? : ( value : number ) => void ; setIsWidthAuto ? : ( value : boolean ) => void ; } ; type UiImageState = { imgRef ? : HTMLImageElement ; isLazyLoaded : boolean ; } ; export class UiImage extends Component < UiImageProps , UiImageState > { state : UiImageState = { imgRef : undefined , isLazyLoaded : false , } ; imgRef : { current : HTMLImageElement | null ; } = createRef ( ) ; getImageSize = ( ) => { this . state . imgRef && this . props . setComputedImageWidth && this . props . setComputedImageWidth ( this . state . imgRef . width ) ; } ; debouncedGetImageSize = debounce ( this . getImageSize , 200 ) ; handleLazyLoaded = ( ) => { this . props . setIsWidthAuto && this . props . setIsWidthAuto ( true ) ; this . getImageSize ( ) ; this . setState ( { isLazyLoaded : true } ) ; } ; componentDidMount ( ) { this . setState ( { imgRef : this . imgRef . current ?? undefined } ) ; this . imgRef . current && this . imgRef . current . addEventListener ( 'lazyloaded' , this . handleLazyLoaded ) ; this . props . setIsWidthAuto && this . props . setIsWidthAuto ( false ) ; window . addEventListener ( 'resize' , this . debouncedGetImageSize ) ; } componentWillUnmount ( ) { window . removeEventListener ( 'resize' , this . debouncedGetImageSize ) ; this . imgRef . current && this . imgRef . current . removeEventListener ( 'lazyloaded' , this . handleLazyLoaded ) ; } render ( ) { const { contentUrl , width , height , alt , tasl , sizesQueries , extraClasses = '' , isFull = false , showTasl = true , isWidthAuto = false , } = this . props ; return ( < Fragment > < noscript className = { `bg-charcoal font-white flex-inline` } dangerouslySetInnerHTML = { { __html : `
          <img width='${ width }'
            height='${ height || '' }'
            class='image image--noscript bg-charcoal font-white'
            src=${ convertImageUri ( contentUrl , 640 ) }
            alt='${ alt || '' }' />` , } } /> < img width = { width } height = { height } onLoad = { this . getImageSize } ref = { this . imgRef } style = { { width : isWidthAuto ? 'auto' : undefined , } } className = { classNames ( { 'lazy-image bg-charcoal font-white' : true , lazyload : true , image : true , [ extraClasses || '' ] : true , } ) } src = { convertImageUri ( contentUrl , 30 ) } data - srcset = { imageSizes ( width ) . map ( size => { return `${ convertImageUri ( contentUrl , size ) } ${ size }w` ; } ) } sizes = { sizesQueries } alt = { alt || '' } /> { showTasl && < Tasl { ... tasl } isFull = { isFull } / > } < /Fragment>); } } export type UiCaptionedImageProps = CaptionedImageType & { sizesQueries : string ; isBody ? : boolean ; preCaptionNode ? : ReactNode ; setTitleStyle ? : ( value : number ) => void ; } ; type UiCaptionedImageState = { computedImageWidth ? : number ; isWidthAuto : boolean ; isEnhanced : boolean ; } ; export class CaptionedImage extends Component < UiCaptionedImageProps , UiCaptionedImageState > { state : UiCaptionedImageState = { computedImageWidth : undefined , isWidthAuto : false , isEnhanced : false , } ; componentDidMount ( ) { this . setState ( { isEnhanced : true , } ) ; } setIsWidthAuto = ( value ) => { this . setState ( { isWidthAuto : value , } ) ; } ; setComputedImageWidth = ( width ) => { this . props . setTitleStyle && this . props . setTitleStyle ( width ) ; this . setState ( { computedImageWidth : width , } ) ; } ; render ( ) { const { caption , preCaptionNode , image , isBody , sizesQueries } = this . props ; const { computedImageWidth , isWidthAuto , isEnhanced } = this . state ; const uiImageProps = { ... image , sizesQueries } ; return ( < CaptionedImageFigure className = { `captioned-image` } isBody = { isBody } > < div style = { { display : isWidthAuto ? 'inline-block' : undefined , } } className = "captioned-image__image-container relative" > { ! isWidthAuto && isEnhanced && < LL />} < UiImage { ... uiImageProps } setIsWidthAuto = { this . setIsWidthAuto } isWidthAuto = { isWidthAuto } setComputedImageWidth = { this . setComputedImageWidth } / > < /div> { isWidthAuto && ( < Caption width = { computedImageWidth } caption = { caption } preCaptionNode = { preCaptionNode } / > ) } { ! isEnhanced && ( < Caption width = { computedImageWidth } caption = { caption } preCaptionNode = { preCaptionNode } / > ) } < /CaptionedImageFigure>); } }