Skip to content

Commit

Permalink
Do not expose menu item fill; simplify PluginPreview component
Browse files Browse the repository at this point in the history
As per the review feedback, there seems to be no need to expose the Preview menu item fill at all. It should be sufficient to expose the title, icon, and click handler. This way we "protect" the Preview menu drop-down from injecting arbitrary, irrelevant elements into it.

Thanks to that, the entire custom previews implementation could be simplified. It's now mostly contained within the `PluginPreview` component itself.
  • Loading branch information
delawski authored and arcangelini committed Oct 25, 2021
1 parent ee1fba2 commit 0301e1d
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 211 deletions.

This file was deleted.

74 changes: 41 additions & 33 deletions docs/designers-developers/developers/slotfills/plugin-preview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,60 @@

Renders the main content area when that menu item is chosen.

It is designed to be used alongside the `PluginPreviewMenuItem` that adds a custom menu item to the "Preview" menu.
A component used to define a custom preview menu item and optional content.

The children of this component will be displayed in the main area of the
block editor, instead of the `VisualEditor` component.

The `title` and `icon` are used to populate the Preview menu item.

## Available Props

- **previewId** `string`: A string identifying the preview. Must match across `PluginPreviewMenuItem` and `PluginPreview`.
- **children** `WPElement`: Preview content.
- **icon** `WPIcon`: Menu item icon to be rendered.
- **name** `string`: A unique name of the custom preview.
- **onClick** `Function`: Menu item click handler, e.g. for previews that provide no content (`children`).
- **title** `string`: Menu item title.

## Example

```js
import { __ } from '@wordpress/i18n';
import { PluginPreview } from '@wordpress/block-editor';
import { registerPlugin } from '@wordpress/plugins';
import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor';
import { external } from '@wordpress/icons';

const PluginPreviewTest = () => (
<>
<PluginPreviewMenuItem previewId="preview-custom-1">
Custom preview 1
</PluginPreviewMenuItem>
<PluginPreview previewId="preview-custom-1">
<div>
<h1>Custom Preview 1 Content</h1>
</div>
</PluginPreview>

<PluginPreviewMenuItem
previewId="preview-custom-2"
onClick={ ( event ) => console.log( event ) }
>
Custom preview 2
</PluginPreviewMenuItem>
<PluginPreview previewId="preview-custom-2">
<div>
<h1>Custom Preview 2 Content</h1>
</div>
</PluginPreview>

<PluginPreviewMenuItem
icon={ external }
onClick={ ( event ) => console.log( event ) }
>
Custom action (no preview)
</PluginPreviewMenuItem>
</>
<>
<PluginPreview
name="preview-custom-1"
title={ __( 'Custom Preview 1' ) }
>
<h1>
{ __( 'Custom Preview 1 Content' ) }
</h1>
</PluginPreview>

<PluginPreview
name="preview-custom-2"
title={ __( 'Custom Preview 2' ) }
onClick={ ( event ) => console.log( event ) }
>
<h1>
{ __( 'Custom Preview 2 Content' ) }
</h1>
</PluginPreview>

<PluginPreview
name="custom-action"
title={ __( 'Custom Action' ) }
icon={ external }
onClick={ ( event ) => console.log( event ) }
/>
</>
);

registerPlugin( 'plugin-preview-test', {
registerPlugin( "plugin-preview-test", {
render: PluginPreviewTest,
} );
```
3 changes: 1 addition & 2 deletions docs/reference-guides/slotfills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ The following SlotFills are available in the `edit-post` package. Please refer t
- [PluginSidebar](/docs/reference-guides/slotfills/plugin-sidebar.md)
- [PluginSidebarMoreMenuItem](/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md)

The following SlotFills are available in the `block-editor` package:
The following SlotFill is available in the `block-editor` package:

- [PluginPreview](/docs/designers-developers/developers/slotfills/plugin-preview.md)
- [PluginPreviewMenuItem](/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md)
29 changes: 10 additions & 19 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,8 @@ one of these values, the built-in `VisualEditor` is responsible for rendering
a preview of that type.

When the `deviceType` is something other than one of the `coreDeviceTypes`,
we are rendering a custom preview registered by the
`<PluginPreviewMenuItem />` and `<PluginPreview />` components, and defer to
a `<Slot />` filled by the plugin to draw the preview.
we are rendering a custom preview registered by the `<PluginPreview />`
component and defer to a `<Slot />` filled by the plugin to draw the preview.

_Type_

Expand Down Expand Up @@ -540,29 +539,21 @@ _Related_

<a name="PluginPreview" href="#PluginPreview">#</a> **PluginPreview**

Component used by a plugin to define the contents of a "custom
preview". The children of this component will be displayed in the main editor
screen when this "custom preview" is chosen from the preview menu.
Component used to define a custom preview menu item and optional content.

_Parameters_

- _props_ `Object`: Component properties.
- _props.previewId_ `string`: The internal name of this custom preview. Must match the `previewId` given to `PluginPreviewMenuItem`.
- _props.children_ `WPElement`: Children to be rendered.

<a name="PluginPreviewMenuItem" href="#PluginPreviewMenuItem">#</a> **PluginPreviewMenuItem**
The children of this component will be displayed in the main area of the
block editor, instead of the `VisualEditor` component.

Component used by a plugin to define the contents of a menu item that
selects a "custom preview". The children of this component will be displayed
inside the preview menu. Typically a single string is good enough.
The `title` and `icon` are used to populate the Preview menu item.

_Parameters_

- _props_ `Object`: Component properties.
- _props.children_ `WPElement`: Children to be rendered.
- _props.children_ `WPElement`: Preview content.
- _props.icon_ `WPIcon`: Menu item icon to be rendered.
- _props.onClick_ `Function`: Menu item click handler, e.g. for previews that do not register slot fills.
- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`.
- _props.name_ `string`: A unique name of the custom preview.
- _props.onClick_ `Function`: Menu item click handler, e.g. for previews that provide no content (`children`).
- _props.title_ `string`: Menu item title.

<a name="PreserveScrollInReorder" href="#PreserveScrollInReorder">#</a> **PreserveScrollInReorder**

Expand Down
6 changes: 5 additions & 1 deletion packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ export { default as withColorContext } from './color-palette/with-color-context'

export { default as __unstableBlockSettingsMenuFirstItem } from './block-settings-menu/block-settings-menu-first-item';
export { default as __unstableInserterMenuExtension } from './inserter-menu-extension';
export { default as __experimentalPreviewOptions } from './preview-options';
export {
default as __experimentalPreviewOptions,
coreDeviceTypes,
} from './preview-options';
export { default as PluginPreview } from './plugin-preview';
export { default as __experimentalUseResizeCanvas } from './use-resize-canvas';
export { default as BlockInspector } from './block-inspector';
export { default as BlockList } from './block-list';
Expand Down
78 changes: 78 additions & 0 deletions packages/block-editor/src/components/plugin-preview/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* WordPress dependencies
*/
import {
__experimentalUseSlot as useSlot,
createSlotFill,
Fill,
MenuItem,
} from '@wordpress/components';
import { check } from '@wordpress/icons';

/**
* Internal dependencies
*/
import { coreDeviceTypes } from '../preview-options';

const {
Fill: PluginPreviewMenuFill,
Slot: PluginPreviewMenuSlot,
} = createSlotFill( 'PluginPreviewMenu' );

export { PluginPreviewMenuSlot };

/**
* Component used to define a custom preview menu item and optional content.
*
* The children of this component will be displayed in the main area of the
* block editor, instead of the `VisualEditor` component.
*
* The `title` and `icon` are used to populate the Preview menu item.
*
* @param {Object} props Component properties.
* @param {WPElement} props.children Preview content.
* @param {WPIcon} props.icon Menu item icon to be rendered.
* @param {string} props.name A unique name of the custom preview.
* @param {Function} props.onClick Menu item click handler, e.g. for previews
* that provide no content (`children`).
* @param {string} props.title Menu item title.
*/
export default function PluginPreview( {
children,
icon,
name,
onClick,
title,
...props
} ) {
const previewSlotName = `core/block-editor/plugin-preview/${ name }`;
const previewSlot = useSlot( previewSlotName );

if ( coreDeviceTypes.includes( name ) ) {
return null;
}

return (
<>
<PluginPreviewMenuFill>
{ ( { deviceType, setDeviceType } ) => (
<MenuItem
onClick={ ( ...args ) => {
if ( name && previewSlot.fills?.length > 0 ) {
setDeviceType( name );
}
if ( onClick ) {
onClick( ...args );
}
} }
icon={ icon || ( deviceType === name && check ) }
{ ...props }
>
{ title }
</MenuItem>
) }
</PluginPreviewMenuFill>
{ children && <Fill name={ previewSlotName }>{ children }</Fill> }
</>
);
}
20 changes: 8 additions & 12 deletions packages/block-editor/src/components/preview-options/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,17 @@ import classnames from 'classnames';
import { useViewportMatch } from '@wordpress/compose';
import {
__experimentalUseSlot as useSlot,
createSlotFill,
DropdownMenu,
MenuGroup,
MenuItem,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { check } from '@wordpress/icons';

const {
Fill: PluginPreviewMenuFill,
Slot: PluginPreviewMenuSlot,
} = createSlotFill( 'PluginPreviewOptionsMenu' );

export { PluginPreviewMenuFill };
/**
* Internal dependencies
*/
import { PluginPreviewMenuSlot } from '../plugin-preview';

/**
* An array of strings that represent `deviceType` values that belong to the
Expand All @@ -33,9 +30,8 @@ export { PluginPreviewMenuFill };
* a preview of that type.
*
* When the `deviceType` is something other than one of the `coreDeviceTypes`,
* we are rendering a custom preview registered by the
* `<PluginPreviewMenuItem />` and `<PluginPreview />` components, and defer to
* a `<Slot />` filled by the plugin to draw the preview.
* we are rendering a custom preview registered by the `<PluginPreview />`
* component and defer to a `<Slot />` filled by the plugin to draw the preview.
*
* @type {Array}
*/
Expand All @@ -48,7 +44,7 @@ export default function PreviewOptions( {
deviceType,
setDeviceType,
} ) {
const slot = useSlot( PluginPreviewMenuSlot.__unstableName );
const previewMenuSlot = useSlot( PluginPreviewMenuSlot.__unstableName );
const isMobile = useViewportMatch( 'small', '<' );
if ( isMobile ) return null;

Expand Down Expand Up @@ -99,7 +95,7 @@ export default function PreviewOptions( {
</MenuItem>
</MenuGroup>

{ slot?.fills?.length && (
{ previewMenuSlot.fills?.length > 0 && (
<MenuGroup>
<PluginPreviewMenuSlot
fillProps={ {
Expand Down
Loading

0 comments on commit 0301e1d

Please sign in to comment.