From f238cfea5446af2fcac85f98b63c5dcb873ead46 Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Thu, 17 Sep 2020 10:45:56 -0500 Subject: [PATCH 1/2] Allow Preview menu to be extendible by plugins: WIP --- .../developers/slotfills/README.md | 27 ++++++----- .../slotfills/plugin-preview-menu-item.md | 37 +++++++++++++++ .../developers/slotfills/plugin-preview.md | 37 +++++++++++++++ packages/block-editor/README.md | 36 +++++++++++++++ .../src/components/preview-options/index.js | 13 +++++- .../plugin-preview-menu-item/index.js | 45 +++++++++++++++++++ .../preview-options/plugin-preview/index.js | 15 +++++++ packages/block-editor/src/index.js | 3 ++ .../edit-post/src/components/layout/index.js | 4 +- .../visual-editor-or-plugin-preview.js | 25 +++++++++++ 10 files changed, 227 insertions(+), 15 deletions(-) create mode 100644 docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md create mode 100644 docs/designers-developers/developers/slotfills/plugin-preview.md create mode 100644 packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js create mode 100644 packages/block-editor/src/components/preview-options/plugin-preview/index.js create mode 100644 packages/edit-post/src/components/visual-editor/visual-editor-or-plugin-preview.js diff --git a/docs/designers-developers/developers/slotfills/README.md b/docs/designers-developers/developers/slotfills/README.md index 3ab5536f55f823..d04e17931a78cc 100644 --- a/docs/designers-developers/developers/slotfills/README.md +++ b/docs/designers-developers/developers/slotfills/README.md @@ -49,9 +49,7 @@ export const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' ); const PluginPostStatusInfo = ( { children, className } ) => ( - - { children } - + { children } ); @@ -97,12 +95,17 @@ const PostStatus = ( { isOpened, onTogglePanel } ) => ( There are currently eight available SlotFills in the `edit-post` package. Please refer to the individual items below for usage and example details: -* [MainDashboardButton](/docs/designers-developers/developers/slotfills/main-dashboard-button.md) -* [PluginBlockSettingsMenuItem](/docs/designers-developers/developers/slotfills/plugin-block-settings-menu-item.md) -* [PluginDocumentSettingPanel](/docs/designers-developers/developers/slotfills/plugin-document-setting-panel.md) -* [PluginMoreMenuItem](/docs/designers-developers/developers/slotfills/plugin-more-menu-item.md) -* [PluginPostPublishPanel](/docs/designers-developers/developers/slotfills/plugin-post-publish-panel.md) -* [PluginPostStatusInfo](/docs/designers-developers/developers/slotfills/plugin-post-status-info.md) -* [PluginPrePublishPanel](/docs/designers-developers/developers/slotfills/plugin-pre-publish-panel.md) -* [PluginSidebar](/docs/designers-developers/developers/slotfills/plugin-sidebar.md) -* [PluginSidebarMoreMenuItem](/docs/designers-developers/developers/slotfills/plugin-sidebar-more-menu-item.md) +- [MainDashboardButton](/docs/designers-developers/developers/slotfills/main-dashboard-button.md) +- [PluginBlockSettingsMenuItem](/docs/designers-developers/developers/slotfills/plugin-block-settings-menu-item.md) +- [PluginDocumentSettingPanel](/docs/designers-developers/developers/slotfills/plugin-document-setting-panel.md) +- [PluginMoreMenuItem](/docs/designers-developers/developers/slotfills/plugin-more-menu-item.md) +- [PluginPostPublishPanel](/docs/designers-developers/developers/slotfills/plugin-post-publish-panel.md) +- [PluginPostStatusInfo](/docs/designers-developers/developers/slotfills/plugin-post-status-info.md) +- [PluginPrePublishPanel](/docs/designers-developers/developers/slotfills/plugin-pre-publish-panel.md) +- [PluginSidebar](/docs/designers-developers/developers/slotfills/plugin-sidebar.md) +- [PluginSidebarMoreMenuItem](/docs/designers-developers/developers/slotfills/plugin-sidebar-more-menu-item.md) + +There are currently two available SlotFills 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) diff --git a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md new file mode 100644 index 00000000000000..55ecfc33ec351e --- /dev/null +++ b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md @@ -0,0 +1,37 @@ +# PluginPreviewMenuItem + +This is designed to be used alongside the PluginPreview. + +- PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. +- PluginPreview: Renders the main content area when that menu item is chosen. + +Each of these takes 2 props, `deviceName`, and `children`. + +- `deviceName` - A string that serves as an internal identifier for your + preview. Must match across PluginPreviewMenuItem and PluginPreview. +- `children` - What gets rendered in that spot. + +## Example + +```js +import { registerPlugin } from '@wordpress/plugins'; +import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; +import { Fragment } from '@wordpress/element'; + +const PluginPreviewTest = () => ( + + + Custom Preview 1 Menu Text + + +
+

Custom Preview 1 Content

+
+
+
+); + +registerPlugin( 'plugin-preview-test', { + render: PluginPreviewTest, +} ); +``` diff --git a/docs/designers-developers/developers/slotfills/plugin-preview.md b/docs/designers-developers/developers/slotfills/plugin-preview.md new file mode 100644 index 00000000000000..905933eb5677bc --- /dev/null +++ b/docs/designers-developers/developers/slotfills/plugin-preview.md @@ -0,0 +1,37 @@ +# PluginPreview + +This is designed to be used alongside the PluginPreviewMenuItem. + +- PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. +- PluginPreview: Renders the main content area when that menu item is chosen. + +Each of these takes 2 props, `deviceName`, and `children`. + +- `deviceName` - A string that serves as an internal identifier for your + preview. Must match across PluginPreviewMenuItem and PluginPreview. +- `children` - What gets rendered in that spot. + +## Example + +```js +import { registerPlugin } from '@wordpress/plugins'; +import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; +import { Fragment } from '@wordpress/element'; + +const PluginPreviewTest = () => ( + + + Custom Preview 1 Menu Text + + +
+

Custom Preview 1 Content

+
+
+
+); + +registerPlugin( 'plugin-preview-test', { + render: PluginPreviewTest, +} ); +``` diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 3bb72598aabf41..3c4be89470f9a1 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -238,6 +238,18 @@ Undocumented declaration. Undocumented declaration. +# **coreDeviceTypes** + +This is an array of strings. The strings returned represent deviceType values +that belong to the core system. When the deviceType, returned by +`__experimentalGetPreviewDeviceType()`, is 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 deviceType registered by the and + components, and defer to a filled by the plugin to +draw the preview. + # **createCustomColorsHOC** A higher-order component factory for creating a 'withCustomColors' HOC, which handles color logic @@ -447,6 +459,30 @@ _Related_ - +# **PluginPreview** + +React 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. + +_Parameters_ + +- _props_ `Object`: Component properties. +- _props.deviceName_ `string`: The internal name of this custom preview. Must + match the _deviceName_ given to `PluginPreviewMenuItem`. +- _props.children_ `WPElement`: Children to be rendered. + +# **PluginPreviewMenuItem** + +React 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. + +- _props_ `Object`: Component properties. +- _props.deviceName_ `string`: The internal name of this custom preview. Must + match the _deviceName_ given to `PluginPreview`. +- _props.children_ `WPElement`: Children to be rendered. + # **PreserveScrollInReorder** Undocumented declaration. diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index 122c85d852d0d2..6872c84ad7e8a7 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -7,10 +7,12 @@ import classnames from 'classnames'; * WordPress dependencies */ import { useViewportMatch } from '@wordpress/compose'; -import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; +import { DropdownMenu, MenuGroup, MenuItem, Slot } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { check } from '@wordpress/icons'; +export const coreDeviceTypes = [ 'Desktop', 'Tablet', 'Mobile' ]; + export default function PreviewOptions( { children, className, @@ -67,6 +69,15 @@ export default function PreviewOptions( { { __( 'Mobile' ) } + + + { ( fills ) => + ! fills || fills.length === 0 ? null : ( + { fills } + ) + } + + { children } ) } diff --git a/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js b/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js new file mode 100644 index 00000000000000..b0cbd71d6c6c9d --- /dev/null +++ b/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js @@ -0,0 +1,45 @@ +/** + * WordPress dependencies + */ +import { Fill, MenuItem } from '@wordpress/components'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { check } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { coreDeviceTypes } from '../index'; + +export default function PluginPreviewMenuItem( { + children, + deviceName, + ...props +} ) { + const { + __experimentalSetPreviewDeviceType: setPreviewDeviceType, + } = useDispatch( 'core/edit-post' ); + + const { deviceType } = useSelect( + ( select ) => ( { + deviceType: select( + 'core/edit-post' + ).__experimentalGetPreviewDeviceType(), + } ), + [] + ); + + if ( coreDeviceTypes.includes( deviceName ) ) { + return null; + } + + return ( + + setPreviewDeviceType( deviceName ) } + icon={ deviceType === deviceName && check } + > + { children } + + + ); +} diff --git a/packages/block-editor/src/components/preview-options/plugin-preview/index.js b/packages/block-editor/src/components/preview-options/plugin-preview/index.js new file mode 100644 index 00000000000000..1f05ecbabd337f --- /dev/null +++ b/packages/block-editor/src/components/preview-options/plugin-preview/index.js @@ -0,0 +1,15 @@ +/** + * WordPress dependencies + */ +import { Fill } from '@wordpress/components'; + +export default function PluginPreview( { children, deviceName, ...props } ) { + return ( + + { children } + + ); +} diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index add6f5a5f9910e..8d54971d0cfa80 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -16,3 +16,6 @@ export * from './components'; export * from './utils'; export { storeConfig } from './store'; export { SETTINGS_DEFAULTS } from './store/defaults'; +export { default as PluginPreviewMenuItem } from './components/preview-options/plugin-preview-menu-item'; +export { default as PluginPreview } from './components/preview-options/plugin-preview'; +export { coreDeviceTypes } from './components/preview-options'; diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 7c99697738b4e4..f42422fb6e0d78 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -39,7 +39,7 @@ import { close } from '@wordpress/icons'; * Internal dependencies */ import TextEditor from '../text-editor'; -import VisualEditor from '../visual-editor'; +import VisualEditorOrPluginPreview from '../visual-editor/visual-editor-or-plugin-preview'; import EditPostKeyboardShortcuts from '../keyboard-shortcuts'; import KeyboardShortcutHelpModal from '../keyboard-shortcut-help-modal'; import ManageBlocksModal from '../manage-blocks-modal'; @@ -246,7 +246,7 @@ function Layout() { ) } { isRichEditingEnabled && mode === 'visual' && ( - + ) }
diff --git a/packages/edit-post/src/components/visual-editor/visual-editor-or-plugin-preview.js b/packages/edit-post/src/components/visual-editor/visual-editor-or-plugin-preview.js new file mode 100644 index 00000000000000..14dd9695cb98c8 --- /dev/null +++ b/packages/edit-post/src/components/visual-editor/visual-editor-or-plugin-preview.js @@ -0,0 +1,25 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { Slot } from '@wordpress/components'; +import { coreDeviceTypes } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import VisualEditor from './index'; + +function VisualEditorOrPluginPreview() { + const deviceType = useSelect( ( select ) => { + return select( 'core/edit-post' ).__experimentalGetPreviewDeviceType(); + }, [] ); + + if ( ! coreDeviceTypes.includes( deviceType ) ) { + return ( + + ); + } + return ; +} +export default VisualEditorOrPluginPreview; From fcc36707f33ac0d334caea5ea9c6bf5a55a428cb Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Fri, 18 Sep 2020 10:27:54 -0500 Subject: [PATCH 2/2] PluginPreview{MenuItem,}: Change external interface "deviceName" -> "previewId" --- .../slotfills/plugin-preview-menu-item.md | 8 +++---- .../developers/slotfills/plugin-preview.md | 8 +++---- packages/block-editor/README.md | 22 ++++++------------- .../src/components/preview-options/index.js | 12 ++++++++++ .../plugin-preview-menu-item/index.js | 17 ++++++++++---- .../preview-options/plugin-preview/index.js | 13 +++++++++-- 6 files changed, 51 insertions(+), 29 deletions(-) diff --git a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md index 55ecfc33ec351e..8ff1e899114a8e 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md @@ -5,9 +5,9 @@ This is designed to be used alongside the PluginPreview. - PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. - PluginPreview: Renders the main content area when that menu item is chosen. -Each of these takes 2 props, `deviceName`, and `children`. +Each of these takes 2 props, `previewId`, and `children`. -- `deviceName` - A string that serves as an internal identifier for your +- `previewId` - A string that serves as an internal identifier for your preview. Must match across PluginPreviewMenuItem and PluginPreview. - `children` - What gets rendered in that spot. @@ -20,10 +20,10 @@ import { Fragment } from '@wordpress/element'; const PluginPreviewTest = () => ( - + Custom Preview 1 Menu Text - +

Custom Preview 1 Content

diff --git a/docs/designers-developers/developers/slotfills/plugin-preview.md b/docs/designers-developers/developers/slotfills/plugin-preview.md index 905933eb5677bc..021df443584c15 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview.md @@ -5,9 +5,9 @@ This is designed to be used alongside the PluginPreviewMenuItem. - PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. - PluginPreview: Renders the main content area when that menu item is chosen. -Each of these takes 2 props, `deviceName`, and `children`. +Each of these takes 2 props, `previewId`, and `children`. -- `deviceName` - A string that serves as an internal identifier for your +- `previewId` - A string that serves as an internal identifier for your preview. Must match across PluginPreviewMenuItem and PluginPreview. - `children` - What gets rendered in that spot. @@ -20,10 +20,10 @@ import { Fragment } from '@wordpress/element'; const PluginPreviewTest = () => ( - + Custom Preview 1 Menu Text - +

Custom Preview 1 Content

diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 3c4be89470f9a1..62dc725c2702ef 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -240,15 +240,7 @@ Undocumented declaration. # **coreDeviceTypes** -This is an array of strings. The strings returned represent deviceType values -that belong to the core system. When the deviceType, returned by -`__experimentalGetPreviewDeviceType()`, is 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 deviceType registered by the and - components, and defer to a filled by the plugin to -draw the preview. +Undocumented declaration. # **createCustomColorsHOC** @@ -461,26 +453,26 @@ _Related_ # **PluginPreview** -React Component; Used by a plugin to define the contents of a "custom +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. _Parameters_ - _props_ `Object`: Component properties. -- _props.deviceName_ `string`: The internal name of this custom preview. Must - match the _deviceName_ given to `PluginPreviewMenuItem`. +- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ given to `PluginPreviewMenuItem`. - _props.children_ `WPElement`: Children to be rendered. # **PluginPreviewMenuItem** -React Component; Used by a plugin to define the contents of a menu item that +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. +_Parameters_ + - _props_ `Object`: Component properties. -- _props.deviceName_ `string`: The internal name of this custom preview. Must - match the _deviceName_ given to `PluginPreview`. +- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`. - _props.children_ `WPElement`: Children to be rendered. # **PreserveScrollInReorder** diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index 6872c84ad7e8a7..ab60cdcb6fb459 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -11,6 +11,18 @@ import { DropdownMenu, MenuGroup, MenuItem, Slot } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { check } from '@wordpress/icons'; +/* + * coreDeviceTypes: An array of strings. The strings returned represent + * deviceType values that belong to the core system. When the deviceType, + * returned by `__experimentalGetPreviewDeviceType()`, is 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 deviceType registered by the and + * components, and defer to a filled by the plugin to + * draw the preview. + */ export const coreDeviceTypes = [ 'Desktop', 'Tablet', 'Mobile' ]; export default function PreviewOptions( { diff --git a/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js b/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js index b0cbd71d6c6c9d..538cb217d47b9f 100644 --- a/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js +++ b/packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js @@ -10,9 +10,18 @@ import { check } from '@wordpress/icons'; */ import { coreDeviceTypes } from '../index'; +/** + * 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. + * + * @param {Object} props Component properties. + * @param {string} props.previewId The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`. + * @param {WPElement} props.children Children to be rendered. + */ export default function PluginPreviewMenuItem( { children, - deviceName, + previewId, ...props } ) { const { @@ -28,15 +37,15 @@ export default function PluginPreviewMenuItem( { [] ); - if ( coreDeviceTypes.includes( deviceName ) ) { + if ( coreDeviceTypes.includes( previewId ) ) { return null; } return ( setPreviewDeviceType( deviceName ) } - icon={ deviceType === deviceName && check } + onClick={ () => setPreviewDeviceType( previewId ) } + icon={ deviceType === previewId && check } > { children } diff --git a/packages/block-editor/src/components/preview-options/plugin-preview/index.js b/packages/block-editor/src/components/preview-options/plugin-preview/index.js index 1f05ecbabd337f..02025afd19ee08 100644 --- a/packages/block-editor/src/components/preview-options/plugin-preview/index.js +++ b/packages/block-editor/src/components/preview-options/plugin-preview/index.js @@ -3,10 +3,19 @@ */ import { Fill } from '@wordpress/components'; -export default function PluginPreview( { children, deviceName, ...props } ) { +/** + * 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. + * + * @param {Object} props Component properties. + * @param {string} props.previewId The internal name of this custom preview. Must match the _previewId_ given to `PluginPreviewMenuItem`. + * @param {WPElement} props.children Children to be rendered. + */ +export default function PluginPreview( { children, previewId, ...props } ) { return ( { children }