Skip to content

Commit

Permalink
BlockPreview: add __experimentalOnReady property (#17242)
Browse files Browse the repository at this point in the history
* Docs: Fix JavaScript linting command (#20371)

The docs say to use run `npm run lint:fix` to automatically fix some issues, that doesn't exist, it should be `npm run lint-js:fix`

* block-preview: update doc

* block-preview: set onReady as experimental prop

* rename reference name

* declare `position` constant

* improve doc

* use onReady name internally

* simply running onReady callback

* pass the online styles to the callback

* avoid var name collisions

* block-preview: reduce the computing delay to 0

* block-preview: be able to set previewing delay

* rename function/vars. Improve docs.

* block-preview: improve Readme doc

* block-preview: fix x position. simplify.

Co-authored-by: Brent Swisher <[email protected]>
  • Loading branch information
retrofox and brentswisher authored Feb 25, 2020
1 parent ef73ed0 commit f054565
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 14 deletions.
29 changes: 29 additions & 0 deletions packages/block-editor/src/components/block-preview/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,32 @@ A block instance (object) or a blocks array you would like to render a preview.
Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview.

`viewportWidth` can be used to simulate how blocks look on different device sizes or to make sure make sure multiple previews will be rendered with the same scale, regardless of their content.

### __experimentalScalingDelay
* **Type** `Int`
* **Default** `100ms`

Defines a delay to be applied before calculating the scale factor and position of the preview block.

### `__experimentalOnReady`
* **Type** `Function`
* **Default:** `noop`

Use this callback as an opportunity to know when the preview is ready. The callback will pass, if available:

* `scale`: the scale factor
* `position`: offsets position (x, y)
* `previewContainerRef`: DOM element reference
* `inlineStyles`: Inline styles applied to the preview container

Eg:

```es6
<BlockPreview
blocks={ blocks }
__experimentalOnReady={ ( { scale, previewContainerRef, position } ) => {
console.log( `scale ${ scale } applied to the <${ previewContainerRef.current.tagName }> element.` );
console.log( `at x: ${ position.x }, y: ${ position.y } position.` );
} }
/>
```
65 changes: 51 additions & 14 deletions packages/block-editor/src/components/block-preview/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { castArray } from 'lodash';
import { castArray, noop } from 'lodash';
import classnames from 'classnames';

/**
Expand All @@ -24,7 +24,21 @@ import BlockEditorProvider from '../provider';
import BlockList from '../block-list';
import { getBlockPreviewContainerDOMNode } from '../../utils/dom';

function ScaledBlockPreview( { blocks, viewportWidth, padding = 0 } ) {
const getInlineStyles = ( scale, x, y, isReady, width ) => ( {
transform: `scale(${ scale })`,
visibility: isReady ? 'visible' : 'hidden',
left: x,
top: y,
width,
} );

function ScaledBlockPreview( {
blocks,
viewportWidth,
padding = 0,
onReady,
scalingDelay,
} ) {
const previewRef = useRef( null );

const [ isReady, setIsReady ] = useState( false );
Expand All @@ -40,6 +54,11 @@ function ScaledBlockPreview( { blocks, viewportWidth, padding = 0 } ) {
return;
}

// Auxiliary vars used for onReady() callback.
let scale,
offsetX = 0,
offsetY = 0;

// If we're previewing a single block, scale the preview to fit it.
if ( blocks.length === 1 ) {
const block = blocks[ 0 ];
Expand All @@ -59,13 +78,13 @@ function ScaledBlockPreview( { blocks, viewportWidth, padding = 0 } ) {
};
const scaledElementRect = previewElement.getBoundingClientRect();

const scale =
scale =
containerElementRect.width / scaledElementRect.width || 1;
const offsetX =
offsetX =
-( scaledElementRect.left - containerElementRect.left ) *
scale +
padding;
const offsetY =
offsetY =
containerElementRect.height >
scaledElementRect.height * scale
? ( containerElementRect.height -
Expand All @@ -81,11 +100,25 @@ function ScaledBlockPreview( { blocks, viewportWidth, padding = 0 } ) {
previewElement.style.marginTop = '0';
} else {
const containerElementRect = containerElement.getBoundingClientRect();
setPreviewScale( containerElementRect.width / viewportWidth );
scale = containerElementRect.width / viewportWidth;
setPreviewScale( scale );
}

setIsReady( true );
}, 100 );
onReady( {
scale,
position: { x: offsetX, y: offsetY },
previewContainerRef: previewRef,

inlineStyles: getInlineStyles(
scale,
offsetX,
offsetY,
true,
viewportWidth
),
} );
}, scalingDelay );

// Cleanup
return () => {
Expand All @@ -99,13 +132,13 @@ function ScaledBlockPreview( { blocks, viewportWidth, padding = 0 } ) {
return null;
}

const previewStyles = {
transform: `scale(${ previewScale })`,
visibility: isReady ? 'visible' : 'hidden',
left: x,
top: y,
width: viewportWidth,
};
const previewStyles = getInlineStyles(
previewScale,
x,
y,
isReady,
viewportWidth
);

return (
<div
Expand Down Expand Up @@ -133,6 +166,8 @@ export function BlockPreview( {
viewportWidth = 700,
padding,
settings,
__experimentalOnReady = noop,
__experimentalScalingDelay = 100,
} ) {
const renderedBlocks = useMemo( () => castArray( blocks ), [ blocks ] );
const [ recompute, triggerRecompute ] = useReducer(
Expand All @@ -152,6 +187,8 @@ export function BlockPreview( {
blocks={ renderedBlocks }
viewportWidth={ viewportWidth }
padding={ padding }
onReady={ __experimentalOnReady }
scalingDelay={ __experimentalScalingDelay }
/>
</BlockEditorProvider>
);
Expand Down

0 comments on commit f054565

Please sign in to comment.