diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 0af013d9dfd83..77c6513003433 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -1,10 +1,15 @@ /** * WordPress dependencies */ +/** + * External dependencies + */ +import React from 'react'; import { __ } from '@wordpress/i18n'; import { createBlock } from '@wordpress/blocks'; import { Disabled } from '@wordpress/components'; import { withSelect } from '@wordpress/data'; +import { useLayoutEffect, useState } from '@wordpress/element'; /** * Internal dependencies @@ -23,32 +28,49 @@ function BlockPreview( props ) { return (
{ __( 'Preview' ) }
- +
); } -export function BlockPreviewContent( { name, attributes, innerBlocks, settings, srcWidth, srcHeight, destWidth } ) { - // Todo: It would be nice if destWidth could be calculated here, that's the only missing piece ot making this fully responsive. +export function BlockPreviewContent( { name, attributes, innerBlocks, settings, srcWidth, srcHeight } = {} ) { + // Calculated the destination width. + const previewRef = React.createRef(); - // Calculate the scale factor necessary to size down the preview thumbnail. - const scale = Math.min( destWidth / srcWidth ); - const previewDimensions = { - width: srcWidth ? srcWidth : 400 + 'px', // 400x300 is provided as a 4:3 aspect ratio fallback. - height: srcHeight ? srcHeight : 300 + 'px', - transform: 'scale(' + scale + ')', - }; + // Fallback dimensions. + const [ previewDimensions, setPreviewDimensions ] = useState( { + width: 400, + height: 300, + transform: 'scale(1)', + } ); - // We use a top-padding to create a responsively sized element with the same aspect ratio as the preview. - // The preview is then absolutely positioned on top of this, creating a visual unit. - const aspectPadding = Math.round( srcHeight / srcWidth * 100 ); - const previewAspect = { - paddingTop: aspectPadding + '%', - }; + const [ previewAspect, setPreviewAspect ] = useState( { + paddingTop: '75%', + } ); + + useLayoutEffect( () => { + const destWidth = previewRef.current.offsetWidth; + + // Calculate the scale factor necessary to size down the preview thumbnail. + const scale = Math.min( destWidth / srcWidth ) || 1; + + setPreviewDimensions( { + width: srcWidth ? srcWidth : 400 + 'px', // 400x300 is provided as a 4:3 aspect ratio fallback. + height: srcHeight ? srcHeight : 300 + 'px', + transform: 'scale(' + scale + ')', + } ); + + // We use a top-padding to create a responsively sized element with the same aspect ratio as the preview. + // The preview is then absolutely positioned on top of this, creating a visual unit. + const aspectPadding = Math.round( srcHeight / srcWidth * 100 ); + setPreviewAspect( { + paddingTop: aspectPadding + '%', + } ); + }, [] ); const block = createBlock( name, attributes, innerBlocks ); return ( -
+