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

Add Inline Images and Inline Blocks API #6959

Merged
merged 14 commits into from
Jun 28, 2018
2 changes: 2 additions & 0 deletions blocks/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export {
} from './registration';
export {
isUnmodifiedDefaultBlock,
normalizeIconObject,
isValidIcon,
} from './utils';
export {
doBlocksMatchTemplate,
Expand Down
8 changes: 2 additions & 6 deletions components/slot-fill/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,9 @@ class Slot extends Component {

const fills = map( getFills( name ), ( fill ) => {
const fillKey = fill.occurrence;
const fillChildren = isFunction( fill.props.children ) ? fill.props.children( fillProps ) : fill.props.children;
Copy link
Member Author

Choose a reason for hiding this comment

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

I made this change to allow null values.

Copy link
Contributor

Choose a reason for hiding this comment

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

We're changing existing functionality, though, right? We're no longer injecting fillKey in "regular" cases (function-as-child).

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think I follow the purpose of this change.

Copy link
Member Author

Choose a reason for hiding this comment

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

How so? There's still a key added. This change is needed because you can't return null when using the function. See https://github.com/WordPress/gutenberg/pull/6959/files#diff-8c9cd11f122f43914bc769f4ad5c36d9R21.


// If a function is passed as a child, render it with the fillProps.
if ( isFunction( fill.props.children ) ) {
return cloneElement( fill.props.children( fillProps ), { key: fillKey } );
}

return Children.map( fill.props.children, ( child, childIndex ) => {
return Children.map( fillChildren, ( child, childIndex ) => {
if ( ! child || isString( child ) ) {
return child;
}
Expand Down
4 changes: 4 additions & 0 deletions core-blocks/gallery/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
width: 100%;
max-height: 100%;
overflow: auto;

img {
display: inline;
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions core-blocks/image/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
&.is-transient img {
@include loading_fade;
}

figcaption img {
display: inline;
}
}

.wp-block-image__resize-handler-top-right,
Expand Down
10 changes: 10 additions & 0 deletions edit-post/hooks/components/media-upload/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class MediaUpload extends Component {
this.onOpen = this.onOpen.bind( this );
this.onSelect = this.onSelect.bind( this );
this.onUpdate = this.onUpdate.bind( this );
this.onClose = this.onClose.bind( this );
this.processMediaCaption = this.processMediaCaption.bind( this );

if ( gallery ) {
Expand Down Expand Up @@ -122,6 +123,7 @@ class MediaUpload extends Component {
this.frame.on( 'select', this.onSelect );
this.frame.on( 'update', this.onUpdate );
this.frame.on( 'open', this.onOpen );
this.frame.on( 'close', this.onClose );
}

componentWillUnmount() {
Expand Down Expand Up @@ -169,6 +171,14 @@ class MediaUpload extends Component {
getAttachmentsCollection( castArray( this.props.value ) ).more();
}

onClose() {
const { onClose } = this.props;

if ( onClose ) {
onClose();
}
}

openModal() {
this.frame.open();
}
Expand Down
5 changes: 4 additions & 1 deletion editor/components/block-types-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ class BlockTypesList extends Component {
}
)
}
onClick={ () => onSelect( item ) }
onClick={ () => {
onSelect( item );
onHover( null );
} }
disabled={ item.isDisabled }
onMouseEnter={ () => onHover( item ) }
onMouseLeave={ () => onHover( null ) }
Expand Down
10 changes: 2 additions & 8 deletions editor/components/inserter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { withSelect, withDispatch } from '@wordpress/data';
*/
import InserterMenu from './menu';

export { default as InserterResultsPortal } from './results-portal';

class Inserter extends Component {
constructor() {
super( ...arguments );
Expand All @@ -22,12 +24,6 @@ class Inserter extends Component {
onToggle( isOpen ) {
const { onToggle } = this.props;

if ( isOpen ) {
this.props.showInsertionPoint();
} else {
this.props.hideInsertionPoint();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

When you insert a block, the insertion point indicator is kept visible. I believe it has to do with these changes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed


// Surface toggle callback to parent component
if ( onToggle ) {
onToggle( isOpen );
Expand Down Expand Up @@ -101,8 +97,6 @@ export default compose( [
};
} ),
withDispatch( ( dispatch, ownProps ) => ( {
showInsertionPoint: dispatch( 'core/editor' ).showInsertionPoint,
hideInsertionPoint: dispatch( 'core/editor' ).hideInsertionPoint,
onInsertBlock: ( item ) => {
const { insertionPoint, selectedBlock } = ownProps;
const { index, rootUID, layout } = insertionPoint;
Expand Down
11 changes: 11 additions & 0 deletions editor/components/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import './style.scss';
import BlockPreview from '../block-preview';
import BlockTypesList from '../block-types-list';
import ChildBlocks from './child-blocks';
import InserterResultsPortal from './results-portal';

const MAX_SUGGESTED_ITEMS = 9;

Expand Down Expand Up @@ -95,6 +96,12 @@ export class InserterMenu extends Component {
this.setState( {
hoveredItem: item,
} );

if ( item ) {
this.props.showInsertionPoint();
} else {
this.props.hideInsertionPoint();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the issue is that we need to hideInsertionPoint when we insert a block (when we close the inserter in general)

}

bindPanel( name ) {
Expand Down Expand Up @@ -201,6 +208,8 @@ export class InserterMenu extends Component {
/>

<div className="editor-inserter__results" ref={ this.inserterResults }>
<InserterResultsPortal.Slot fillProps={ { filterValue } } />

<ChildBlocks
rootUID={ rootUID }
items={ childItems }
Expand Down Expand Up @@ -275,6 +284,8 @@ export default compose(
} ),
withDispatch( ( dispatch ) => ( {
fetchSharedBlocks: dispatch( 'core/editor' ).fetchSharedBlocks,
showInsertionPoint: dispatch( 'core/editor' ).showInsertionPoint,
hideInsertionPoint: dispatch( 'core/editor' ).hideInsertionPoint,
} ) ),
withSpokenMessages,
withInstanceId,
Expand Down
38 changes: 38 additions & 0 deletions editor/components/inserter/results-portal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* WordPress dependencies
*/
import { createSlotFill, PanelBody } from '@wordpress/components';

/**
* Internal dependencies
*/
import BlockTypesList from '../block-types-list';
import { searchItems } from './menu';

const { Fill, Slot } = createSlotFill( 'InserterResultsPortal' );

const InserterResultsPortal = ( { items, title, onSelect, onHover } ) => {
return (
<Fill>
{ ( { filterValue } ) => {
const filteredItems = searchItems( items, filterValue );

if ( ! filteredItems.length ) {
return null;
}

return (
<PanelBody
title={ title }
>
<BlockTypesList items={ filteredItems } onSelect={ onSelect } onHover={ onHover } />
</PanelBody>
);
} }
</Fill>
);
};

InserterResultsPortal.Slot = Slot;

export default InserterResultsPortal;
11 changes: 11 additions & 0 deletions editor/components/rich-text/core-tokens/image/editor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.mce-content-body div.mce-resizehandle {
border-radius: 50%;
border: 2px solid $white;
width: 15px !important;
height: 15px !important;
position: absolute;
background: theme( primary );
padding: 0 3px 3px 0;
box-sizing: border-box;
cursor: se-resize;
}
48 changes: 48 additions & 0 deletions editor/components/rich-text/core-tokens/image/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import './editor.scss';
import MediaUpload from '../../../media-upload';

export const name = 'core/image';

export const settings = {
id: 'image',

title: __( 'Inline Image' ),

type: 'image',

icon: 'format-image',

edit( { onSave } ) {
return (
<MediaUpload
type="image"
onSelect={ ( media ) => onSave( media ) }
onClose={ () => onSave( null ) }
render={ ( { open } ) => {
open();
return null;
} }
/>
);
},

save( { id, url, alt, width } ) {
return (
<img
className={ `wp-image-${ id }` }
// set width in style attribute to prevent Block CSS from overriding it
style={ { width: `${ Math.min( width, 150 ) }px` } }
src={ url }
alt={ alt }
/>
);
},
};
6 changes: 6 additions & 0 deletions editor/components/rich-text/core-tokens/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Internal dependencies
*/
import * as image from './image';

export { image };
7 changes: 7 additions & 0 deletions editor/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { pickAriaProps } from './aria';
import patterns from './patterns';
import { withBlockEditContext } from '../block-edit/context';
import { domToFormat, valueToString } from './format';
import TokenUI from './tokens/ui';

const { BACKSPACE, DELETE, ENTER, rawShortcut } = keycodes;

Expand Down Expand Up @@ -887,6 +888,12 @@ export class RichText extends Component {
{ formatToolbar }
</div>
) }
{ isSelected &&
<TokenUI
Copy link
Contributor

Choose a reason for hiding this comment

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

Would a better name be InsertableRichTextTokens, InsertableInlineTokens?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm also a bit torn on the module name ./tokens/ui. When reviewing this diff it took me longer to distinguish the pieces. Would something more explicit like ./tokens/inserter-fill be clearer?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, makes sense.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually inserter-fill is not the only thing it's doing. We can move it in a folder though.

editor={ this.editor }
containerRef={ this.containerRef }
/>
}
<Autocomplete onReplace={ this.props.onReplace } completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<Fragment>
Expand Down
10 changes: 10 additions & 0 deletions editor/components/rich-text/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@
}
}

img {
&[data-mce-selected] {
outline: none;
}

&::selection {
background: none !important;
}
}

&[data-is-placeholder-visible="true"] {
position: absolute;
top: 0;
Expand Down
Loading