Skip to content

Commit

Permalink
Simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Dec 10, 2020
1 parent 999ec09 commit 7279dce
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 143 deletions.
231 changes: 93 additions & 138 deletions packages/block-editor/src/components/iframe/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/**
* WordPress dependencies
*/
import { useState, useEffect, createPortal, useRef } from '@wordpress/element';
import { useState, createPortal } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useResizeObserver } from '@wordpress/compose';

const BODY_CLASS_NAME = 'editor-styles-wrapper';
const BLOCK_PREFIX = 'wp-block';
Expand All @@ -18,36 +17,34 @@ const BLOCK_PREFIX = 'wp-block';
*
* @param {Document} doc The document to append cloned stylesheets to.
*/
function useStyleSheetsCompat( doc ) {
useEffect( () => {
// Search the document for stylesheets targetting the editor canvas.
Array.from( document.styleSheets ).forEach( ( styleSheet ) => {
try {
// May fail for external styles.
// eslint-disable-next-line no-unused-expressions
styleSheet.cssRules;
} catch ( e ) {
return;
}
function styleSheetsCompat( doc ) {
// Search the document for stylesheets targetting the editor canvas.
Array.from( document.styleSheets ).forEach( ( styleSheet ) => {
try {
// May fail for external styles.
// eslint-disable-next-line no-unused-expressions
styleSheet.cssRules;
} catch ( e ) {
return;
}

const { ownerNode, cssRules } = styleSheet;
const { ownerNode, cssRules } = styleSheet;

if ( ! cssRules ) {
return;
}
if ( ! cssRules ) {
return;
}

const isMatch = Array.from( cssRules ).find(
( { selectorText } ) =>
selectorText &&
( selectorText.includes( `.${ BODY_CLASS_NAME }` ) ||
selectorText.includes( `.${ BLOCK_PREFIX }` ) )
);
const isMatch = Array.from( cssRules ).find(
( { selectorText } ) =>
selectorText &&
( selectorText.includes( `.${ BODY_CLASS_NAME }` ) ||
selectorText.includes( `.${ BLOCK_PREFIX }` ) )
);

if ( isMatch && ! doc.getElementById( ownerNode.id ) ) {
doc.head.appendChild( ownerNode.cloneNode( true ) );
}
} );
}, [] );
if ( isMatch && ! doc.getElementById( ownerNode.id ) ) {
doc.head.appendChild( ownerNode.cloneNode( true ) );
}
} );
}

/**
Expand All @@ -60,48 +57,40 @@ function useStyleSheetsCompat( doc ) {
*
* @param {Document} doc Document to attach listeners to.
*/
function useBubbleEvents( doc ) {
useEffect( () => {
const { defaultView } = doc;
const { frameElement } = defaultView;

function bubbleEvent( event ) {
const prototype = Object.getPrototypeOf( event );
const constructorName = prototype.constructor.name;
const Constructor = window[ constructorName ];
function bubbleEvents( doc ) {
const { defaultView } = doc;
const { frameElement } = defaultView;

const init = {};
function bubbleEvent( event ) {
const prototype = Object.getPrototypeOf( event );
const constructorName = prototype.constructor.name;
const Constructor = window[ constructorName ];

for ( const key in event ) {
init[ key ] = event[ key ];
}
const init = {};

if ( event instanceof defaultView.MouseEvent ) {
const rect = frameElement.getBoundingClientRect();
init.clientX += rect.left;
init.clientY += rect.top;
}

const newEvent = new Constructor( event.type, init );
const cancelled = ! frameElement.dispatchEvent( newEvent );
for ( const key in event ) {
init[ key ] = event[ key ];
}

if ( cancelled ) {
event.preventDefault();
}
if ( event instanceof defaultView.MouseEvent ) {
const rect = frameElement.getBoundingClientRect();
init.clientX += rect.left;
init.clientY += rect.top;
}

const eventTypes = [ 'keydown', 'keypress', 'dragover' ];
const newEvent = new Constructor( event.type, init );
const cancelled = ! frameElement.dispatchEvent( newEvent );

for ( const name of eventTypes ) {
doc.addEventListener( name, bubbleEvent );
if ( cancelled ) {
event.preventDefault();
}
}

return () => {
for ( const name of eventTypes ) {
doc.removeEventListener( name, bubbleEvent );
}
};
}, [] );
const eventTypes = [ 'keydown', 'keypress', 'dragover' ];

for ( const name of eventTypes ) {
doc.addEventListener( name, bubbleEvent );
}
}

/**
Expand All @@ -114,36 +103,15 @@ function useBubbleEvents( doc ) {
*
* @param {Document} doc Document to add class name to.
*/
function useBodyClassName( doc ) {
useEffect( () => {
doc.dir = document.dir;
doc.body.className = BODY_CLASS_NAME;

for ( const name of document.body.classList ) {
if ( name.startsWith( 'admin-color-' ) ) {
doc.body.classList.add( name );
}
}
}, [] );
}
function setBodyClassName( doc ) {
doc.dir = document.dir;
doc.body.className = BODY_CLASS_NAME;

/**
* Positions the body element so that the resize listener works correctly. We're
* using an absolute position here because the resize listener doesn't seem to
* report shrinking when the position is relative, causing the iframe not to
* shrink when content is removed.
*
* @see https://github.com/FezVrasta/react-resize-aware#usage
*
* @param {Document} doc Document to set styles to.
*/
function useResizeListenerCompat( doc ) {
useEffect( () => {
// Necessary for the resize listener to work correctly.
doc.body.style.position = 'absolute';
doc.body.style.right = '0';
doc.body.style.left = '0';
}, [] );
for ( const name of document.body.classList ) {
if ( name.startsWith( 'admin-color-' ) ) {
doc.body.classList.add( name );
}
}
}

/**
Expand All @@ -152,48 +120,45 @@ function useResizeListenerCompat( doc ) {
* @param {Document} doc Document to set the head for.
* @param {string} head HTML to set as the head.
*/
function useHead( doc, head ) {
useEffect( () => {
doc.head.innerHTML =
// Body margin must be overridable by themes.
'<style>body{margin:0}</style>' +
'<style>.wp-block[data-align="full"],.wp-block.alignfull{max-width:100vw!important;width:100vw!important;}</style>' +
head;
}, [] );
function setHead( doc, head ) {
doc.head.innerHTML =
// Body margin must be overridable by themes.
'<style>body{margin:0}</style>' + head;
}

function IframeContent( { doc, head, children } ) {
useHead( doc, head );
useStyleSheetsCompat( doc );
useBubbleEvents( doc );
useBodyClassName( doc );
useResizeListenerCompat( doc );
return createPortal( children, doc.body );
}

export default function Iframe( { children, head, style = {}, ...props } ) {
const [ resizeListener, sizes ] = useResizeObserver();
const [ contentDocument, setContentDocument ] = useState();
const ref = useRef();

function setDocumentIfReady( doc ) {
const { readyState } = doc;

if ( readyState === 'interactive' || readyState === 'complete' ) {
setContentDocument( doc );
export default function Iframe( {
contentRef,
children,
head,
style = {},
...props
} ) {
const [ iframeDocument, setIframeDocument ] = useState();

function setRef( node ) {
if ( ! node ) {
return;
}
}

useEffect( () => {
setDocumentIfReady( ref.current.contentDocument );
}, [] );
function setDocumentIfReady() {
const { contentDocument } = node;
const { readyState } = contentDocument;

if ( readyState === 'interactive' || readyState === 'complete' ) {
setIframeDocument( contentDocument );
setHead( contentDocument, head );
setBodyClassName( contentDocument );
styleSheetsCompat( contentDocument );
bubbleEvents( contentDocument );
setBodyClassName( contentDocument );
contentRef.current = contentDocument.body;
}
}

function setRef( newRef ) {
ref.current = newRef;
setDocumentIfReady();

if ( newRef ) {
setDocumentIfReady( newRef.contentDocument );
}
// Document is not immediately loaded in Firefox.
node.addEventListener( 'load', setDocumentIfReady );
}

return (
Expand All @@ -202,25 +167,15 @@ export default function Iframe( { children, head, style = {}, ...props } ) {
style={ {
display: 'block',
width: '100%',
height: sizes.height + 'px',
minHeight: '100%',
height: '100%',
...style,
} }
ref={ setRef }
tabIndex="0"
title={ __( 'Editor canvas' ) }
name="editor-canvas"
onLoad={ () => {
// Document is not immediately loaded in Firefox.
setDocumentIfReady( ref.current.contentDocument );
} }
>
{ contentDocument && (
<IframeContent doc={ contentDocument } head={ head }>
{ children( { current: contentDocument.body } ) }
{ resizeListener }
</IframeContent>
) }
{ iframeDocument && createPortal( children, iframeDocument.body ) }
</iframe>
);
}
16 changes: 11 additions & 5 deletions packages/edit-site/src/components/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { useCallback, useRef } from '@wordpress/element';
import { useEntityBlockEditor } from '@wordpress/core-data';
import {
BlockEditorProvider,
Expand Down Expand Up @@ -65,6 +65,13 @@ export default function BlockEditor( { setIsInserterOpen } ) {
const { setPage } = useDispatch( 'core/edit-site' );

const resizedCanvasStyles = useResizeCanvas( deviceType, true );
const contentRef = useRef();

// Allow scrolling "through" popovers over the canvas. This is only called
// for as long as the pointer is over a popover.
function onWheel( { deltaX, deltaY } ) {
contentRef.current.scrollBy( deltaX, deltaY );
}

return (
<BlockEditorProvider
Expand All @@ -91,15 +98,14 @@ export default function BlockEditor( { setIsInserterOpen } ) {
<SidebarInspectorFill>
<BlockInspector />
</SidebarInspectorFill>
<div className="edit-site-visual-editor">
<div className="edit-site-visual-editor" onWheel={ onWheel }>
<Popover.Slot name="block-toolbar" />
<Iframe
style={ resizedCanvasStyles }
head={ window.__editorStyles.html }
contentRef={ contentRef }
>
{ ( body ) => (
<Canvas body={ body } styles={ settings.styles } />
) }
<Canvas body={ contentRef } styles={ settings.styles } />
</Iframe>
</div>
</BlockEditorProvider>
Expand Down
7 changes: 7 additions & 0 deletions packages/edit-site/src/components/editor/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,15 @@
}
}

.interface-interface-skeleton__content {
// The iframe is scrollable, so no need for the content area to be
// scrollable too.
overflow: visible;
}

.edit-site-visual-editor {
position: relative;
height: 100%;

iframe {
background-color: $white;
Expand Down

0 comments on commit 7279dce

Please sign in to comment.