import React from "react" ; import { Image } from "@webiny/ui/Image" ; import { ImageComponentPlugin } from "../types" ; const SUPPORTED_IMAGE_RESIZE_WIDTHS = [ 100 , 300 , 500 , 750 , 1000 , 1500 , 2500 ] ; /**
 * Width of the image should not be just any random number. For optimization reasons,
 * we only allow the ones listed in SUPPORTED_IMAGE_RESIZE_WIDTHS list (Webiny Cloud supports only these).
 */ const getSupportedImageResizeWidth = width => { let output = SUPPORTED_IMAGE_RESIZE_WIDTHS [ 0 ] ; let i = SUPPORTED_IMAGE_RESIZE_WIDTHS . length ; while ( i >= 0 ) { if ( width === SUPPORTED_IMAGE_RESIZE_WIDTHS [ i ] ) { output = SUPPORTED_IMAGE_RESIZE_WIDTHS [ i ] ; break ; } if ( width > SUPPORTED_IMAGE_RESIZE_WIDTHS [ i ] ) { output = SUPPORTED_IMAGE_RESIZE_WIDTHS [ i + 1 ] ; if ( ! output ) { output = SUPPORTED_IMAGE_RESIZE_WIDTHS [ i ] ; } break ; } i -- ; } return output ; } ; param args const sanitizeTransformArgs = ( args ) : Object => { const output = { } ; if ( args ) { const width = parseInt ( args . width ) ; if ( width > 0 ) { output . width = getSupportedImageResizeWidth ( width ) ; } } return output ; } ; const getSizes = ( width ) : string | null => { if ( typeof width === "string" && width . endsWith ( "%" ) ) { return `${ parseInt ( width ) }vw` ; } if ( typeof width === "string" && width . endsWith ( "vw" ) ) { return `${ parseInt ( width ) }vw` ; } if ( typeof width === "string" && width . endsWith ( "em" ) ) { return `${ parseInt ( width ) }em` ; } return null ; } ; const isFixedImageWidth = width => { if ( Number . isFinite ( width ) ) { return true ; } if ( typeof width === "string" && width . endsWith ( "px" ) ) { return true ; } return false ; } ; const getSrcSetAutoSizes = ( max ) => { max = isFixedImageWidth ( max ) ? parseInt ( "" + max ) : 2500 ; const maxWidth = getSupportedImageResizeWidth ( max ) ; return SUPPORTED_IMAGE_RESIZE_WIDTHS . filter ( ( supportedWidth ) => { return supportedWidth <= maxWidth ; } ) ; } ; const convertTransformToQueryParams = ( transform ) : string => { return Object . keys ( transform ) . map ( key => `${ key }=${ transform [ key ] }` ) . join ( "&" ) ; } ; export default ( ) => { const imagePlugin = { name : "image-component" , type : "image-component" , presets : { avatar : { width : 300 } } , getImageSrc : ( props ) => { if ( ! props ) { return "" ; } const { src , transform } = props ; if ( ! transform ) { return src ; } if ( ! src || src . startsWith ( "data:" ) || src . endsWith ( "svg" ) ) { return src ; } let params = sanitizeTransformArgs ( transform ) ; params = convertTransformToQueryParams ( params ) ; return src + "?" + params ; } , render ( props ) { const { transform , srcSet : srcSetInitial , ... imageProps } = props ; let srcSet = srcSetInitial ; let sizes ; const src = imageProps . src ; if ( srcSet && srcSet === "auto" ) { srcSet = { } ; const forcedWidth = props . width || ( props . style && props . style . width ) ; const srcSetAutoWidths = getSrcSetAutoSizes ( forcedWidth ) ; srcSetAutoWidths . forEach ( width => { srcSet [ width + "w" ] = imagePlugin . getImageSrc ( { src , transform : { ... transform , width } } ) ; } ) ; sizes = getSizes ( forcedWidth ) ; } return < Image { ... imageProps } srcSet = { srcSet } src = { src } sizes = { sizes } / > ; } } ; return imagePlugin ; } ;