Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Framework: Drop the focus/setFocus props from block edit functions #4872

Merged
merged 11 commits into from
Feb 7, 2018
8 changes: 4 additions & 4 deletions blocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ want to display alignment options in the selected block's toolbar.

Because the toolbar should only be shown when the block is selected, it is
important that a `BlockControls` element is only returned when the block's
`focus` prop is
`isSelected` prop is
[truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy),
meaning that focus is currently within the block.
meaning that the block is currently selected.

Example:

Expand All @@ -291,8 +291,8 @@ Example:

function edit( props ) {
return [
// Controls: (only visible when focused)
props.focus && (
// Controls: (only visible when block is selected)
props.isSelected && (
el( BlockControls, { key: 'controls' },
el( AlignmentToolbar, {
value: props.align,
Expand Down
2 changes: 1 addition & 1 deletion blocks/block-controls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Toolbar, Fill } from '@wordpress/components';

export default function BlockControls( { controls, children } ) {
return (
<Fill name="Formatting.Toolbar">
<Fill name="Block.Toolbar">
<Toolbar controls={ controls } />
{ children }
</Fill>
Expand Down
2 changes: 1 addition & 1 deletion blocks/block-controls/test/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`BlockControls Should render a dynamic toolbar of controls 1`] = `
<Fill
name="Formatting.Toolbar"
name="Block.Toolbar"
>
<Toolbar
controls={
Expand Down
12 changes: 11 additions & 1 deletion blocks/block-edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
import { noop } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -36,7 +37,16 @@ export function BlockEdit( props ) {
// them preferencially as the render value for the block.
const Edit = blockType.edit || blockType.save;

return <Edit { ...props } className={ className } />;
// For backwards compatibility concerns adds a focus and setFocus prop
// These should be removed after some time (maybe when merging to Core)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's worth looking for availability of window.Proxy and, if so, return an instance of it?

focus = new Proxy( {}, { get() { console.warn( 'deprecated' ) } } )
return <Edit  focus={ focus } />
> focus
< Proxy { <target>: {}, <handler>: {…} }

> focus.editable
⚠ deprecated
< undefined

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it 👍

Copy link
Contributor Author

@youknowriad youknowriad Feb 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second thought, we'd have to proxify the props object to do so, which I think is not really possible :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I guess it's fine, it seems supported where we need it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'd have to proxify the props object

What do you mean by this? I was just thinking of the following pseudo-code:

if not isSelected: focus = false
else:
  if browserHasProxySupport: focus = deprecatedEmptyObject
  else: focus = {}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to find a way to proxy any access to props.focus (and not focus.*) because the main use-case for this prop is just checking truthiness to show the block toolbar/inspector

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha.

return (
<Edit
{ ...props }
className={ className }
focus={ props.isSelected ? {} : false }
setFocus={ noop }
/>
);
}

export default withFilters( 'blocks.BlockEdit' )( BlockEdit );
11 changes: 4 additions & 7 deletions blocks/library/audio/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const settings = {
}
render() {
const { align, caption, id } = this.props.attributes;
const { setAttributes, focus, setFocus } = this.props;
const { setAttributes, isSelected } = this.props;
const { editing, className, src } = this.state;
const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } );
const switchToEditing = () => {
Expand All @@ -93,7 +93,7 @@ export const settings = {
}
return false;
};
const controls = focus && (
const controls = isSelected && (
<BlockControls key="controls">
<BlockAlignmentToolbar
value={ align }
Expand All @@ -110,8 +110,6 @@ export const settings = {
</BlockControls>
);

const focusCaption = ( focusValue ) => setFocus( { editable: 'caption', ...focusValue } );

if ( editing ) {
return [
controls,
Expand Down Expand Up @@ -153,14 +151,13 @@ export const settings = {
controls,
<figure key="audio" className={ className }>
<audio controls="controls" src={ src } />
{ ( ( caption && caption.length ) || !! focus ) && (
{ ( ( caption && caption.length ) || !! isSelected ) && (
<RichText
tagName="figcaption"
placeholder={ __( 'Write caption…' ) }
value={ caption }
focus={ focus && focus.editable === 'caption' ? focus : undefined }
onFocus={ focusCaption }
onChange={ ( value ) => setAttributes( { caption: value } ) }
isSelected={ isSelected }
inlineToolbar
/>
) }
Expand Down
6 changes: 3 additions & 3 deletions blocks/library/block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class ReusableBlockEdit extends Component {
}

render() {
const { focus, reusableBlock, isFetching, isSaving } = this.props;
const { isSelected, reusableBlock, isFetching, isSaving } = this.props;
const { isEditing, title, attributes } = this.state;

if ( ! reusableBlock && isFetching ) {
Expand All @@ -105,12 +105,12 @@ class ReusableBlockEdit extends Component {
<BlockEdit
{ ...this.props }
name={ reusableBlock.type }
focus={ isEditing ? focus : null }
isSelected={ isEditing && isSelected }
attributes={ reusableBlockAttributes }
setAttributes={ isEditing ? this.setAttributes : noop }
/>
</div>,
focus && (
isSelected && (
<ReusableBlockEditPanel
key="panel"
isEditing={ isEditing }
Expand Down
12 changes: 5 additions & 7 deletions blocks/library/button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ class ButtonBlock extends Component {
const {
attributes,
setAttributes,
focus,
setFocus,
isSelected,
className,
} = this.props;

Expand All @@ -76,7 +75,7 @@ class ButtonBlock extends Component {
} = attributes;

return [
focus && (
isSelected && (
<BlockControls key="controls">
<BlockAlignmentToolbar value={ align } onChange={ this.updateAlignment } />
</BlockControls>
Expand All @@ -86,18 +85,17 @@ class ButtonBlock extends Component {
tagName="span"
placeholder={ __( 'Add text…' ) }
value={ text }
focus={ focus }
onFocus={ setFocus }
onChange={ ( value ) => setAttributes( { text: value } ) }
formattingControls={ [ 'bold', 'italic', 'strikethrough' ] }
className="wp-block-button__link"
style={ {
backgroundColor: color,
color: textColor,
} }
isSelected={ isSelected }
keepPlaceholderOnFocus
/>
{ focus &&
{ isSelected &&
<InspectorControls key="inspector">
<ToggleControl
label={ __( 'Wrap text' ) }
Expand Down Expand Up @@ -125,7 +123,7 @@ class ButtonBlock extends Component {
</InspectorControls>
}
</span>,
focus && (
isSelected && (
<form
key="form-link"
className="blocks-button__inline-link"
Expand Down
12 changes: 5 additions & 7 deletions blocks/library/cover-image/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const settings = {
}
},

edit( { attributes, setAttributes, focus, setFocus, className } ) {
edit( { attributes, setAttributes, isSelected, className } ) {
const { url, title, align, contentAlign, id, hasParallax, dimRatio } = attributes;
const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } );
const onSelectImage = ( media ) => setAttributes( { url: media.url, id: media.id } );
Expand Down Expand Up @@ -124,7 +124,7 @@ export const settings = {
} }
/>
);
const controls = focus && [
const controls = isSelected && [
<BlockControls key="controls">
<BlockAlignmentToolbar
value={ align }
Expand Down Expand Up @@ -176,9 +176,8 @@ export const settings = {
<RichText
tagName="h2"
value={ title }
focus={ focus }
onFocus={ setFocus }
onChange={ ( value ) => setAttributes( { title: value } ) }
isSelected={ isSelected }
inlineToolbar
/>
) : __( 'Cover Image' );
Expand All @@ -199,14 +198,13 @@ export const settings = {
style={ style }
className={ classes }
>
{ title || !! focus ? (
{ title || isSelected ? (
<RichText
tagName="h2"
placeholder={ __( 'Write title…' ) }
value={ title }
focus={ focus }
onFocus={ setFocus }
onChange={ ( value ) => setAttributes( { title: value } ) }
isSelected={ isSelected }
inlineToolbar
/>
) : null }
Expand Down
10 changes: 4 additions & 6 deletions blocks/library/embed/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ function getEmbedBlockSettings( { title, icon, category = 'embed', transforms, k
render() {
const { html, type, error, fetching } = this.state;
const { align, url, caption } = this.props.attributes;
const { setAttributes, focus, setFocus } = this.props;
const { setAttributes, isSelected } = this.props;
const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } );

const controls = focus && (
const controls = isSelected && (
<BlockControls key="controls">
<BlockAlignmentToolbar
value={ align }
Expand Down Expand Up @@ -200,18 +200,16 @@ function getEmbedBlockSettings( { title, icon, category = 'embed', transforms, k
html={ html }
title={ iframeTitle }
type={ type }
onFocus={ () => setFocus() }
/>
</div>
) }
{ ( caption && caption.length > 0 ) || !! focus ? (
{ ( caption && caption.length > 0 ) || isSelected ? (
<RichText
tagName="figcaption"
placeholder={ __( 'Write caption…' ) }
value={ caption }
focus={ focus }
onFocus={ setFocus }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change regressed on the fix introduced by #4011, where in that case I explicitly wanted to handle focus within the iframe. Can we otherwise expose manually setting a block as selected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean like a onSelect prop or something? I'd prefer to avoid it in favor of a global event but if it's not possible for iframes, we could provide it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could see about generalizing the blur check which occurs in Sandbox, to see if focus has transitioned to an iframe within a block:

componentDidMount() {
window.addEventListener( 'message', this.checkMessageForResize, false );
window.addEventListener( 'blur', this.checkFocus );
this.trySandbox();
}
componentDidUpdate() {
this.trySandbox();
}
componentWillUnmount() {
window.removeEventListener( 'message', this.checkMessageForResize );
window.removeEventListener( 'blur', this.checkFocus );
}
checkFocus() {
if ( this.props.onFocus && document.activeElement === this.iframe ) {
this.props.onFocus();
}
}

onChange={ ( value ) => setAttributes( { caption: value } ) }
isSelected={ isSelected }
inlineToolbar
/>
) : null }
Expand Down
12 changes: 2 additions & 10 deletions blocks/library/freeform/old-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ export default class OldEditor extends Component {
if ( prevProps.attributes.content !== content ) {
editor.setContent( content || '' );
}

if ( ! prevProps.focus && !! this.props.focus && document.activeElement !== editor.getBody() ) {
editor.getBody().focus();
}
}

initialize() {
Expand Down Expand Up @@ -127,10 +123,6 @@ export default class OldEditor extends Component {
// See wp-includes/js/tinymce/plugins/wordpress/plugin.js
// Swaps node.nodeName === 'BODY' to node === editor.getBody()
editor.on( 'init', () => {
if ( this.props.focus && document.activeElement !== editor.getBody() ) {
editor.getBody().focus();
}

editor.addCommand( 'WP_More', function( tag ) {
var parent, html, title,
classname = 'wp-more-tag',
Expand Down Expand Up @@ -176,15 +168,15 @@ export default class OldEditor extends Component {
}

render() {
const { focus, id, className } = this.props;
const { isSelected, id, className } = this.props;

return [
<div
key="toolbar"
id={ id + '-toolbar' }
ref={ ref => this.ref = ref }
className="freeform-toolbar"
style={ ! focus ? { display: 'none' } : {} }
style={ ! isSelected ? { display: 'none' } : {} }
/>,
<div
key="editor"
Expand Down
Loading