From 81d03cbb38d70b068b4c5b93d24613c9983ae66b Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Thu, 17 Sep 2020 10:45:56 -0500 Subject: [PATCH 01/20] Allow Preview menu to be extendible by plugins: WIP --- .../slotfills/plugin-preview-menu-item.md | 37 +++++++++++++++ .../developers/slotfills/plugin-preview.md | 37 +++++++++++++++ docs/reference-guides/slotfills/README.md | 5 +++ 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, 217 insertions(+), 3 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/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/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index 5c7af9a39e3b1f..28e5a23ec6abec 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -104,3 +104,8 @@ The following SlotFills are available in the `edit-post` package. Please refer t - [PluginPrePublishPanel](/docs/reference-guides/slotfills/plugin-pre-publish-panel.md) - [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: + +- [PluginPreview](/docs/designers-developers/developers/slotfills/plugin-preview.md) +- [PluginPreviewMenuItem](/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 726990f0ac3637..73307c2a79e0bf 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -270,6 +270,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 @@ -495,6 +507,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 27af4c4be666b8..100d5677a7ef5b 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -18,3 +18,6 @@ export * from './components'; export * from './utils'; export { storeConfig, store } 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 21115811d75892..9bd3b7c3c1040b 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -33,7 +33,7 @@ import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; * 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'; @@ -225,7 +225,7 @@ function Layout( { styles } ) { ) } { 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 64cb27d536b422d9bda5559b85908b05ad3f602a Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Fri, 18 Sep 2020 10:27:54 -0500 Subject: [PATCH 02/20] 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 73307c2a79e0bf..2284c61a68f31a 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -272,15 +272,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** @@ -509,26 +501,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 } From a690338407cac72b563f4d031c35b4a6f05415ee Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Wed, 12 May 2021 16:08:54 +0200 Subject: [PATCH 03/20] Decouple PluginPreviewMenuItem from @wordpress/edit-post --- .../src/components/preview-options/index.js | 33 +++++++++++---- .../plugin-preview-menu-item/index.js | 42 +++++++------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index ab60cdcb6fb459..70d96652c72270 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -7,10 +7,23 @@ import classnames from 'classnames'; * WordPress dependencies */ import { useViewportMatch } from '@wordpress/compose'; -import { DropdownMenu, MenuGroup, MenuItem, Slot } from '@wordpress/components'; +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 }; + /* * coreDeviceTypes: An array of strings. The strings returned represent * deviceType values that belong to the core system. When the deviceType, @@ -32,6 +45,7 @@ export default function PreviewOptions( { deviceType, setDeviceType, } ) { + const slot = useSlot( PluginPreviewMenuSlot.__unstableName ); const isMobile = useViewportMatch( 'small', '<' ); if ( isMobile ) return null; @@ -82,13 +96,16 @@ export default function PreviewOptions( { - - { ( fills ) => - ! fills || fills.length === 0 ? null : ( - { fills } - ) - } - + { slot?.fills?.length && ( + + + + ) } { 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 index 538cb217d47b9f..7927810174394d 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 @@ -1,54 +1,42 @@ /** * WordPress dependencies */ -import { Fill, MenuItem } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { MenuItem } from '@wordpress/components'; import { check } from '@wordpress/icons'; /** * Internal dependencies */ -import { coreDeviceTypes } from '../index'; +import { coreDeviceTypes, PluginPreviewMenuFill } 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. + * @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, previewId, ...props } ) { - const { - __experimentalSetPreviewDeviceType: setPreviewDeviceType, - } = useDispatch( 'core/edit-post' ); - - const { deviceType } = useSelect( - ( select ) => ( { - deviceType: select( - 'core/edit-post' - ).__experimentalGetPreviewDeviceType(), - } ), - [] - ); - if ( coreDeviceTypes.includes( previewId ) ) { return null; } return ( - - setPreviewDeviceType( previewId ) } - icon={ deviceType === previewId && check } - > - { children } - - + + { ( { deviceType, setDeviceType } ) => ( + setDeviceType( previewId ) } + icon={ deviceType === previewId && check } + > + { children } + + ) } + ); } From bfb8976b2d9dd3beef629f1802dca0df6433b7f4 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 16:54:09 +0200 Subject: [PATCH 04/20] Retrieve previewId in parent component --- .../preview-options/plugin-preview/index.js | 2 +- .../edit-post/src/components/layout/index.js | 9 ++++++++- .../visual-editor-or-plugin-preview.js | 20 ++++++++----------- 3 files changed, 17 insertions(+), 14 deletions(-) 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 02025afd19ee08..21c0d9f712ccbe 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 @@ -15,7 +15,7 @@ import { Fill } from '@wordpress/components'; export default function PluginPreview( { children, previewId, ...props } ) { return ( { children } diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 9bd3b7c3c1040b..771cda9e51f63b 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -85,6 +85,7 @@ function Layout( { styles } ) { showIconLabels, hasReducedUI, showBlockBreadcrumbs, + previewId, } = useSelect( ( select ) => { const editorSettings = select( editorStore ).getEditorSettings(); return { @@ -121,6 +122,9 @@ function Layout( { styles } ) { showBlockBreadcrumbs: select( editPostStore ).isFeatureActive( 'showBlockBreadcrumbs' ), + previewId: select( + editPostStore + ).__experimentalGetPreviewDeviceType(), }; }, [] ); const className = classnames( 'edit-post-layout', 'is-mode-' + mode, { @@ -225,7 +229,10 @@ function Layout( { styles } ) { ) } { 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 index 14dd9695cb98c8..d67f3c1386ff53 100644 --- 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 @@ -1,25 +1,21 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; -import { Slot } from '@wordpress/components'; -import { coreDeviceTypes } from '@wordpress/block-editor'; +import { __experimentalUseSlot as useSlot, Slot } from '@wordpress/components'; /** * Internal dependencies */ import VisualEditor from './index'; -function VisualEditorOrPluginPreview() { - const deviceType = useSelect( ( select ) => { - return select( 'core/edit-post' ).__experimentalGetPreviewDeviceType(); - }, [] ); +function VisualEditorOrPluginPreview( { previewId, ...props } ) { + const slotName = `core/block-editor/plugin-preview/${ previewId }`; + const slot = useSlot( slotName ); - if ( ! coreDeviceTypes.includes( deviceType ) ) { - return ( - - ); + if ( slot?.fills?.length === 0 ) { + return ; } - return ; + + return ; } export default VisualEditorOrPluginPreview; From 36bca61b1066187deaf2d022bc022b75179cdca4 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 21:36:38 +0200 Subject: [PATCH 05/20] Accept custom onClick handler and icon in plugin preview --- packages/block-editor/README.md | 6 ++++-- .../plugin-preview-menu-item/index.js | 20 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 2284c61a68f31a..a4f0b1d566f522 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -508,7 +508,7 @@ screen when this "custom preview" is chosen from the preview menu. _Parameters_ - _props_ `Object`: Component properties. -- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ 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** @@ -520,8 +520,10 @@ inside the preview menu. Typically a single string is good enough. _Parameters_ - _props_ `Object`: Component properties. -- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`. - _props.children_ `WPElement`: Children to be rendered. +- _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`. # **PreserveScrollInReorder** 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 7927810174394d..87616d07b58155 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 @@ -15,11 +15,15 @@ import { coreDeviceTypes, PluginPreviewMenuFill } from '../index'; * 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. + * @param {WPIcon} props.icon Menu item icon to be rendered. + * @param {Function} props.onClick Menu item click handler, e.g. for previews that do not register slot fills. + * @param {string} props.previewId The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`. */ export default function PluginPreviewMenuItem( { children, + icon, + onClick, previewId, ...props } ) { @@ -28,11 +32,19 @@ export default function PluginPreviewMenuItem( { } return ( - + { ( { deviceType, setDeviceType } ) => ( setDeviceType( previewId ) } - icon={ deviceType === previewId && check } + onClick={ ( ...args ) => { + if ( previewId ) { + setDeviceType( previewId ); + } + if ( onClick ) { + onClick( ...args ); + } + } } + icon={ icon || ( deviceType === previewId && check ) } + { ...props } > { children } From 5a933221aeb6e4f8c50b227230fb6207fb4a8a03 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 21:37:24 +0200 Subject: [PATCH 06/20] Update jsdoc blocks --- .../src/components/preview-options/plugin-preview/index.js | 6 +++--- .../visual-editor/visual-editor-or-plugin-preview.js | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) 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 21c0d9f712ccbe..f2ec6784432da7 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 @@ -8,9 +8,9 @@ import { Fill } from '@wordpress/components'; * 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. + * @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 ( 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 index d67f3c1386ff53..44e1b63809f866 100644 --- 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 @@ -8,6 +8,12 @@ import { __experimentalUseSlot as useSlot, Slot } from '@wordpress/components'; */ import VisualEditor from './index'; +/** + * Component that renders a preview slot fill if found or a VisualEditor instead. + * + * @param {Object} props Component properties. + * @param {string} props.previewId The internal name of this custom preview. + */ function VisualEditorOrPluginPreview( { previewId, ...props } ) { const slotName = `core/block-editor/plugin-preview/${ previewId }`; const slot = useSlot( slotName ); From d7c329ebc2d125640ae3f8946e8baa307dc9474e Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 22:02:25 +0200 Subject: [PATCH 07/20] Check previewId aka deviceType directly in child component --- .../edit-post/src/components/layout/index.js | 9 +-------- .../visual-editor-or-plugin-preview.js | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 771cda9e51f63b..9bd3b7c3c1040b 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -85,7 +85,6 @@ function Layout( { styles } ) { showIconLabels, hasReducedUI, showBlockBreadcrumbs, - previewId, } = useSelect( ( select ) => { const editorSettings = select( editorStore ).getEditorSettings(); return { @@ -122,9 +121,6 @@ function Layout( { styles } ) { showBlockBreadcrumbs: select( editPostStore ).isFeatureActive( 'showBlockBreadcrumbs' ), - previewId: select( - editPostStore - ).__experimentalGetPreviewDeviceType(), }; }, [] ); const className = classnames( 'edit-post-layout', 'is-mode-' + mode, { @@ -229,10 +225,7 @@ function Layout( { styles } ) { ) } { 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 index 44e1b63809f866..1146a4dca5d88a 100644 --- 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 @@ -2,26 +2,32 @@ * WordPress dependencies */ import { __experimentalUseSlot as useSlot, Slot } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import VisualEditor from './index'; +import { store as editPostStore } from '../../store'; /** * Component that renders a preview slot fill if found or a VisualEditor instead. * - * @param {Object} props Component properties. - * @param {string} props.previewId The internal name of this custom preview. + * @param {Object} props Component properties. */ -function VisualEditorOrPluginPreview( { previewId, ...props } ) { +function VisualEditorOrPluginPreview( props ) { + const previewId = useSelect( + ( select ) => + select( editPostStore ).__experimentalGetPreviewDeviceType(), + [] + ); const slotName = `core/block-editor/plugin-preview/${ previewId }`; const slot = useSlot( slotName ); - if ( slot?.fills?.length === 0 ) { - return ; + if ( slot?.fills?.length > 0 ) { + return ; } - return ; + return ; } export default VisualEditorOrPluginPreview; From 18f2596908d1280626158b5b4e2a9e253e22098e Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 22:10:03 +0200 Subject: [PATCH 08/20] Update coreDeviceTypes docs --- packages/block-editor/README.md | 16 +++++++++++- .../src/components/preview-options/index.js | 25 +++++++++++-------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index a4f0b1d566f522..2427de60c45771 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -272,7 +272,21 @@ Undocumented declaration. # **coreDeviceTypes** -Undocumented declaration. +An array of strings that represent `deviceType` values that belong to the +block editor 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 preview registered by the +`` and `` components, and defer to +a `` filled by the plugin to draw the preview. + +_Type_ + +- `Array` # **createCustomColorsHOC** diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index 70d96652c72270..ef5491690e2ba3 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -24,17 +24,20 @@ const { export { PluginPreviewMenuFill }; -/* - * 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. +/** + * An array of strings that represent `deviceType` values that belong to the + * block editor 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 preview registered by the + * `` and `` components, and defer to + * a `` filled by the plugin to draw the preview. + * + * @type {Array} */ export const coreDeviceTypes = [ 'Desktop', 'Tablet', 'Mobile' ]; From f4e401b50639d2a22d35c295bdae1fb1debe8af7 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 22:36:52 +0200 Subject: [PATCH 09/20] Update slotfills docs --- .../slotfills/plugin-preview-menu-item.md | 46 +++++++++++----- .../developers/slotfills/plugin-preview.md | 52 ++++++++++++------- 2 files changed, 68 insertions(+), 30 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 8ff1e899114a8e..fc40135cf9c9a7 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md @@ -1,34 +1,56 @@ # PluginPreviewMenuItem -This is designed to be used alongside the PluginPreview. +Adds a menu item to the "Preview" menu. -- PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. -- PluginPreview: Renders the main content area when that menu item is chosen. +It is designed to be used alongside the `PluginPreview` that renders a custom preview instead of the `VisualEditor` in the block editor. -Each of these takes 2 props, `previewId`, and `children`. +The presence of the `PluginPreview` component is not necessary. +Selecting a preview will not replace the `VisualEditor` with a custom preview in such a case. +Instead, a plugin author may rely on the `onClick` event handler entirely. -- `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. +## Available Props + +- **previewId** `string`: A string identifying the preview. When used, must match across `PluginPreviewMenuItem` and `PluginPreview`. +- **icon** `(string|Element)`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element. +- **onClick** `Function`: Click handler, e.g. for previews that do not register slot fills. ## Example ```js import { registerPlugin } from '@wordpress/plugins'; import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; -import { Fragment } from '@wordpress/element'; +import { external } from '@wordpress/icons'; const PluginPreviewTest = () => ( - + <> - Custom Preview 1 Menu Text + Custom preview 1
-

Custom Preview 1 Content

+

Custom Preview 1 Content

+
+
+ + console.log( event ) } + > + Custom preview 2 + + +
+

Custom Preview 2 Content

-
+ + console.log( event ) } + > + Custom action (no preview) + + ); registerPlugin( 'plugin-preview-test', { diff --git a/docs/designers-developers/developers/slotfills/plugin-preview.md b/docs/designers-developers/developers/slotfills/plugin-preview.md index 021df443584c15..f51ca83ceca5fe 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview.md @@ -1,34 +1,50 @@ # PluginPreview -This is designed to be used alongside the PluginPreviewMenuItem. +Renders the main content area when that menu item is chosen. -- PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. -- PluginPreview: 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. -Each of these takes 2 props, `previewId`, and `children`. +## Available Props -- `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. +- **previewId** `string`: A string identifying the preview. Must match across `PluginPreviewMenuItem` and `PluginPreview`. ## Example ```js import { registerPlugin } from '@wordpress/plugins'; import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; -import { Fragment } from '@wordpress/element'; +import { external } from '@wordpress/icons'; const PluginPreviewTest = () => ( - - - Custom Preview 1 Menu Text - - -
-

Custom Preview 1 Content

-
-
-
+ <> + + Custom preview 1 + + +
+

Custom Preview 1 Content

+
+
+ + console.log( event ) } + > + Custom preview 2 + + +
+

Custom Preview 2 Content

+
+
+ + console.log( event ) } + > + Custom action (no preview) + + ); registerPlugin( 'plugin-preview-test', { From f949647c7b256ed12529585ba76aa7610b113467 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Mon, 24 May 2021 14:45:12 +0200 Subject: [PATCH 10/20] Do not expose menu item fill; simplify PluginPreview component 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. --- .../slotfills/plugin-preview-menu-item.md | 59 -------------- .../developers/slotfills/plugin-preview.md | 74 ++++++++++-------- docs/reference-guides/slotfills/README.md | 3 +- packages/block-editor/README.md | 29 +++---- packages/block-editor/src/components/index.js | 6 +- .../src/components/plugin-preview/index.js | 78 +++++++++++++++++++ .../src/components/preview-options/index.js | 20 ++--- .../plugin-preview-menu-item/index.js | 54 ------------- .../preview-options/plugin-preview/index.js | 24 ------ packages/block-editor/src/index.js | 3 - .../visual-editor-or-plugin-preview.js | 8 +- 11 files changed, 147 insertions(+), 211 deletions(-) delete mode 100644 docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md create mode 100644 packages/block-editor/src/components/plugin-preview/index.js delete mode 100644 packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js delete mode 100644 packages/block-editor/src/components/preview-options/plugin-preview/index.js diff --git a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md deleted file mode 100644 index fc40135cf9c9a7..00000000000000 --- a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md +++ /dev/null @@ -1,59 +0,0 @@ -# PluginPreviewMenuItem - -Adds a menu item to the "Preview" menu. - -It is designed to be used alongside the `PluginPreview` that renders a custom preview instead of the `VisualEditor` in the block editor. - -The presence of the `PluginPreview` component is not necessary. -Selecting a preview will not replace the `VisualEditor` with a custom preview in such a case. -Instead, a plugin author may rely on the `onClick` event handler entirely. - -## Available Props - -- **previewId** `string`: A string identifying the preview. When used, must match across `PluginPreviewMenuItem` and `PluginPreview`. -- **icon** `(string|Element)`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element. -- **onClick** `Function`: Click handler, e.g. for previews that do not register slot fills. - -## Example - -```js -import { registerPlugin } from '@wordpress/plugins'; -import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; -import { external } from '@wordpress/icons'; - -const PluginPreviewTest = () => ( - <> - - Custom preview 1 - - -
-

Custom Preview 1 Content

-
-
- - console.log( event ) } - > - Custom preview 2 - - -
-

Custom Preview 2 Content

-
-
- - console.log( event ) } - > - Custom action (no preview) - - -); - -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 index f51ca83ceca5fe..f950deda2533c9 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview.md @@ -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 = () => ( - <> - - Custom preview 1 - - -
-

Custom Preview 1 Content

-
-
- - console.log( event ) } - > - Custom preview 2 - - -
-

Custom Preview 2 Content

-
-
- - console.log( event ) } - > - Custom action (no preview) - - + <> + +

+ { __( 'Custom Preview 1 Content' ) } +

+
+ + console.log( event ) } + > +

+ { __( 'Custom Preview 2 Content' ) } +

+
+ + console.log( event ) } + /> + ); -registerPlugin( 'plugin-preview-test', { +registerPlugin( "plugin-preview-test", { render: PluginPreviewTest, } ); ``` diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index 28e5a23ec6abec..21ce0902912402 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -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) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 2427de60c45771..39c5bbcf9fa04c 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -280,9 +280,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 -`` and `` components, and defer to -a `` filled by the plugin to draw the preview. +we are rendering a custom preview registered by the `` +component and defer to a `` filled by the plugin to draw the preview. _Type_ @@ -515,29 +514,21 @@ _Related_ # **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. - -# **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. # **PreserveScrollInReorder** diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 51d9ba8c1a0dbe..6121337908541b 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -89,7 +89,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'; diff --git a/packages/block-editor/src/components/plugin-preview/index.js b/packages/block-editor/src/components/plugin-preview/index.js new file mode 100644 index 00000000000000..785f0c012a5518 --- /dev/null +++ b/packages/block-editor/src/components/plugin-preview/index.js @@ -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 ( + <> + + { ( { deviceType, setDeviceType } ) => ( + { + if ( name && previewSlot.fills?.length > 0 ) { + setDeviceType( name ); + } + if ( onClick ) { + onClick( ...args ); + } + } } + icon={ icon || ( deviceType === name && check ) } + { ...props } + > + { title } + + ) } + + { children && { children } } + + ); +} diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index ef5491690e2ba3..7a95732fad45e3 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -9,7 +9,6 @@ import classnames from 'classnames'; import { useViewportMatch } from '@wordpress/compose'; import { __experimentalUseSlot as useSlot, - createSlotFill, DropdownMenu, MenuGroup, MenuItem, @@ -17,12 +16,10 @@ import { 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 @@ -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 - * `` and `` components, and defer to - * a `` filled by the plugin to draw the preview. + * we are rendering a custom preview registered by the `` + * component and defer to a `` filled by the plugin to draw the preview. * * @type {Array} */ @@ -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; @@ -99,7 +95,7 @@ export default function PreviewOptions( { - { slot?.fills?.length && ( + { previewMenuSlot.fills?.length > 0 && ( - { ( { deviceType, setDeviceType } ) => ( - { - if ( previewId ) { - setDeviceType( previewId ); - } - if ( onClick ) { - onClick( ...args ); - } - } } - icon={ icon || ( deviceType === previewId && check ) } - { ...props } - > - { 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 deleted file mode 100644 index f2ec6784432da7..00000000000000 --- a/packages/block-editor/src/components/preview-options/plugin-preview/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * WordPress dependencies - */ -import { Fill } from '@wordpress/components'; - -/** - * 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 } - - ); -} diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index 100d5677a7ef5b..27af4c4be666b8 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -18,6 +18,3 @@ export * from './components'; export * from './utils'; export { storeConfig, store } 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/visual-editor/visual-editor-or-plugin-preview.js b/packages/edit-post/src/components/visual-editor/visual-editor-or-plugin-preview.js index 1146a4dca5d88a..dadf43021a0308 100644 --- 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 @@ -21,11 +21,11 @@ function VisualEditorOrPluginPreview( props ) { select( editPostStore ).__experimentalGetPreviewDeviceType(), [] ); - const slotName = `core/block-editor/plugin-preview/${ previewId }`; - const slot = useSlot( slotName ); + const previewSlotName = `core/block-editor/plugin-preview/${ previewId }`; + const previewSlot = useSlot( previewSlotName ); - if ( slot?.fills?.length > 0 ) { - return ; + if ( previewSlot.fills?.length > 0 ) { + return ; } return ; From 9abd3d00052b68f4157382de51960112d6e4bb3a Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Thu, 17 Sep 2020 10:45:56 -0500 Subject: [PATCH 11/20] Allow Preview menu to be extendible by plugins: WIP --- .../slotfills/plugin-preview-menu-item.md | 37 +++++++++++++++ .../developers/slotfills/plugin-preview.md | 37 +++++++++++++++ docs/reference-guides/slotfills/README.md | 5 +++ packages/block-editor/README.md | 40 ++++++++++++++++- .../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, 219 insertions(+), 5 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/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/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index 5be4de892073d1..bbf0cfe70cc117 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -104,3 +104,8 @@ The following SlotFills are available in the `edit-post` package. Please refer t - [PluginPrePublishPanel](/docs/reference-guides/slotfills/plugin-pre-publish-panel.md) - [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: + +- [PluginPreview](/docs/designers-developers/developers/slotfills/plugin-preview.md) +- [PluginPreviewMenuItem](/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index da2515ead12b03..c6ab1a9b04b124 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -281,7 +281,19 @@ Undocumented declaration. Undocumented declaration. -### createCustomColorsHOC +# **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 for class generation color value, retrieval and color attribute setting. @@ -520,7 +532,31 @@ _Related_ - -### PreserveScrollInReorder +# **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 5fb6ba1063bd45..2db2ce0275a042 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 2720c2cd4c9588..6e014b740a7861 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -14,3 +14,6 @@ export * from './components'; export * from './utils'; export { storeConfig, store } 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 f0bd691a1019ff..2306398367536e 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -34,7 +34,7 @@ import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; * 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 PreferencesModal from '../preferences-modal'; @@ -228,7 +228,7 @@ function Layout( { styles } ) { ) } { isRichEditingEnabled && mode === 'visual' && ( - + ) } { ! isTemplateMode && (
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 590744185bf8dc9d2cf949e2aa12d008d21ab703 Mon Sep 17 00:00:00 2001 From: Matthew Reishus Date: Fri, 18 Sep 2020 10:27:54 -0500 Subject: [PATCH 12/20] 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 c6ab1a9b04b124..0119feede33a60 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -283,15 +283,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** @@ -534,26 +526,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 2db2ce0275a042..0c261b59f00109 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 } From 0a7d495e630dd7f8a41256eb29429e55958f12b9 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Wed, 12 May 2021 16:08:54 +0200 Subject: [PATCH 13/20] Decouple PluginPreviewMenuItem from @wordpress/edit-post --- .../src/components/preview-options/index.js | 33 +++++++++++---- .../plugin-preview-menu-item/index.js | 42 +++++++------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index 0c261b59f00109..2d444e40606c9b 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -7,10 +7,23 @@ import classnames from 'classnames'; * WordPress dependencies */ import { useViewportMatch } from '@wordpress/compose'; -import { DropdownMenu, MenuGroup, MenuItem, Slot } from '@wordpress/components'; +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 }; + /* * coreDeviceTypes: An array of strings. The strings returned represent * deviceType values that belong to the core system. When the deviceType, @@ -32,6 +45,7 @@ export default function PreviewOptions( { deviceType, setDeviceType, } ) { + const slot = useSlot( PluginPreviewMenuSlot.__unstableName ); const isMobile = useViewportMatch( 'small', '<' ); if ( isMobile ) return null; @@ -82,13 +96,16 @@ export default function PreviewOptions( { - - { ( fills ) => - ! fills || fills.length === 0 ? null : ( - { fills } - ) - } - + { slot?.fills?.length && ( + + + + ) } { 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 index 538cb217d47b9f..7927810174394d 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 @@ -1,54 +1,42 @@ /** * WordPress dependencies */ -import { Fill, MenuItem } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { MenuItem } from '@wordpress/components'; import { check } from '@wordpress/icons'; /** * Internal dependencies */ -import { coreDeviceTypes } from '../index'; +import { coreDeviceTypes, PluginPreviewMenuFill } 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. + * @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, previewId, ...props } ) { - const { - __experimentalSetPreviewDeviceType: setPreviewDeviceType, - } = useDispatch( 'core/edit-post' ); - - const { deviceType } = useSelect( - ( select ) => ( { - deviceType: select( - 'core/edit-post' - ).__experimentalGetPreviewDeviceType(), - } ), - [] - ); - if ( coreDeviceTypes.includes( previewId ) ) { return null; } return ( - - setPreviewDeviceType( previewId ) } - icon={ deviceType === previewId && check } - > - { children } - - + + { ( { deviceType, setDeviceType } ) => ( + setDeviceType( previewId ) } + icon={ deviceType === previewId && check } + > + { children } + + ) } + ); } From cd9a6d1b8741ed7f4131fa79dbd0480a6480b0c1 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 16:54:09 +0200 Subject: [PATCH 14/20] Retrieve previewId in parent component --- .../preview-options/plugin-preview/index.js | 2 +- .../edit-post/src/components/layout/index.js | 13 +++++++----- .../visual-editor-or-plugin-preview.js | 20 ++++++++----------- 3 files changed, 17 insertions(+), 18 deletions(-) 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 02025afd19ee08..21c0d9f712ccbe 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 @@ -15,7 +15,7 @@ import { Fill } from '@wordpress/components'; export default function PluginPreview( { children, previewId, ...props } ) { return ( { children } diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 2306398367536e..2feb100604c09a 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -85,8 +85,7 @@ function Layout( { styles } ) { showIconLabels, hasReducedUI, showBlockBreadcrumbs, - isTemplateMode, - documentLabel, + previewId, } = useSelect( ( select ) => { const { getEditorSettings, getPostTypeLabel } = select( editorStore ); const editorSettings = getEditorSettings(); @@ -125,8 +124,9 @@ function Layout( { styles } ) { showBlockBreadcrumbs: select( editPostStore ).isFeatureActive( 'showBlockBreadcrumbs' ), - // translators: Default label for the Document in the Block Breadcrumb. - documentLabel: postTypeLabel || _x( 'Document', 'noun' ), + previewId: select( + editPostStore + ).__experimentalGetPreviewDeviceType(), }; }, [] ); const className = classnames( 'edit-post-layout', 'is-mode-' + mode, { @@ -228,7 +228,10 @@ function Layout( { styles } ) { ) } { isRichEditingEnabled && mode === 'visual' && ( - + ) } { ! isTemplateMode && (
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 index 14dd9695cb98c8..d67f3c1386ff53 100644 --- 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 @@ -1,25 +1,21 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; -import { Slot } from '@wordpress/components'; -import { coreDeviceTypes } from '@wordpress/block-editor'; +import { __experimentalUseSlot as useSlot, Slot } from '@wordpress/components'; /** * Internal dependencies */ import VisualEditor from './index'; -function VisualEditorOrPluginPreview() { - const deviceType = useSelect( ( select ) => { - return select( 'core/edit-post' ).__experimentalGetPreviewDeviceType(); - }, [] ); +function VisualEditorOrPluginPreview( { previewId, ...props } ) { + const slotName = `core/block-editor/plugin-preview/${ previewId }`; + const slot = useSlot( slotName ); - if ( ! coreDeviceTypes.includes( deviceType ) ) { - return ( - - ); + if ( slot?.fills?.length === 0 ) { + return ; } - return ; + + return ; } export default VisualEditorOrPluginPreview; From dc79b50dd76c6a0d477cc4e740d1ef9750e70bfa Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 21:36:38 +0200 Subject: [PATCH 15/20] Accept custom onClick handler and icon in plugin preview --- packages/block-editor/README.md | 6 ++++-- .../plugin-preview-menu-item/index.js | 20 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 0119feede33a60..43704154d85b7b 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -533,7 +533,7 @@ screen when this "custom preview" is chosen from the preview menu. _Parameters_ - _props_ `Object`: Component properties. -- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ 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** @@ -545,8 +545,10 @@ inside the preview menu. Typically a single string is good enough. _Parameters_ - _props_ `Object`: Component properties. -- _props.previewId_ `string`: The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`. - _props.children_ `WPElement`: Children to be rendered. +- _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`. # **PreserveScrollInReorder** 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 7927810174394d..87616d07b58155 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 @@ -15,11 +15,15 @@ import { coreDeviceTypes, PluginPreviewMenuFill } from '../index'; * 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. + * @param {WPIcon} props.icon Menu item icon to be rendered. + * @param {Function} props.onClick Menu item click handler, e.g. for previews that do not register slot fills. + * @param {string} props.previewId The internal name of this custom preview. Must match the _previewId_ given to `PluginPreview`. */ export default function PluginPreviewMenuItem( { children, + icon, + onClick, previewId, ...props } ) { @@ -28,11 +32,19 @@ export default function PluginPreviewMenuItem( { } return ( - + { ( { deviceType, setDeviceType } ) => ( setDeviceType( previewId ) } - icon={ deviceType === previewId && check } + onClick={ ( ...args ) => { + if ( previewId ) { + setDeviceType( previewId ); + } + if ( onClick ) { + onClick( ...args ); + } + } } + icon={ icon || ( deviceType === previewId && check ) } + { ...props } > { children } From 866e5c88a2c0b2be004908e602ebe2183f421e57 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 21:37:24 +0200 Subject: [PATCH 16/20] Update jsdoc blocks --- .../src/components/preview-options/plugin-preview/index.js | 6 +++--- .../visual-editor/visual-editor-or-plugin-preview.js | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) 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 21c0d9f712ccbe..f2ec6784432da7 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 @@ -8,9 +8,9 @@ import { Fill } from '@wordpress/components'; * 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. + * @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 ( 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 index d67f3c1386ff53..44e1b63809f866 100644 --- 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 @@ -8,6 +8,12 @@ import { __experimentalUseSlot as useSlot, Slot } from '@wordpress/components'; */ import VisualEditor from './index'; +/** + * Component that renders a preview slot fill if found or a VisualEditor instead. + * + * @param {Object} props Component properties. + * @param {string} props.previewId The internal name of this custom preview. + */ function VisualEditorOrPluginPreview( { previewId, ...props } ) { const slotName = `core/block-editor/plugin-preview/${ previewId }`; const slot = useSlot( slotName ); From a309d23828dfca65af22ceba25e1eb5508b617e0 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 22:02:25 +0200 Subject: [PATCH 17/20] Check previewId aka deviceType directly in child component --- .../edit-post/src/components/layout/index.js | 9 +-------- .../visual-editor-or-plugin-preview.js | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 2feb100604c09a..f3d73690191fb8 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -85,7 +85,6 @@ function Layout( { styles } ) { showIconLabels, hasReducedUI, showBlockBreadcrumbs, - previewId, } = useSelect( ( select ) => { const { getEditorSettings, getPostTypeLabel } = select( editorStore ); const editorSettings = getEditorSettings(); @@ -124,9 +123,6 @@ function Layout( { styles } ) { showBlockBreadcrumbs: select( editPostStore ).isFeatureActive( 'showBlockBreadcrumbs' ), - previewId: select( - editPostStore - ).__experimentalGetPreviewDeviceType(), }; }, [] ); const className = classnames( 'edit-post-layout', 'is-mode-' + mode, { @@ -228,10 +224,7 @@ function Layout( { styles } ) { ) } { isRichEditingEnabled && mode === 'visual' && ( - + ) } { ! isTemplateMode && (
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 index 44e1b63809f866..1146a4dca5d88a 100644 --- 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 @@ -2,26 +2,32 @@ * WordPress dependencies */ import { __experimentalUseSlot as useSlot, Slot } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import VisualEditor from './index'; +import { store as editPostStore } from '../../store'; /** * Component that renders a preview slot fill if found or a VisualEditor instead. * - * @param {Object} props Component properties. - * @param {string} props.previewId The internal name of this custom preview. + * @param {Object} props Component properties. */ -function VisualEditorOrPluginPreview( { previewId, ...props } ) { +function VisualEditorOrPluginPreview( props ) { + const previewId = useSelect( + ( select ) => + select( editPostStore ).__experimentalGetPreviewDeviceType(), + [] + ); const slotName = `core/block-editor/plugin-preview/${ previewId }`; const slot = useSlot( slotName ); - if ( slot?.fills?.length === 0 ) { - return ; + if ( slot?.fills?.length > 0 ) { + return ; } - return ; + return ; } export default VisualEditorOrPluginPreview; From 4cd207581c195d3c64710c380b64eb86f64d2ca8 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 22:10:03 +0200 Subject: [PATCH 18/20] Update coreDeviceTypes docs --- packages/block-editor/README.md | 16 +++++++++++- .../src/components/preview-options/index.js | 25 +++++++++++-------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 43704154d85b7b..f428942d6d8d85 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -283,7 +283,21 @@ Undocumented declaration. # **coreDeviceTypes** -Undocumented declaration. +An array of strings that represent `deviceType` values that belong to the +block editor 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 preview registered by the +`` and `` components, and defer to +a `` filled by the plugin to draw the preview. + +_Type_ + +- `Array` # **createCustomColorsHOC** diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index 2d444e40606c9b..44e0d8b540d137 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -24,17 +24,20 @@ const { export { PluginPreviewMenuFill }; -/* - * 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. +/** + * An array of strings that represent `deviceType` values that belong to the + * block editor 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 preview registered by the + * `` and `` components, and defer to + * a `` filled by the plugin to draw the preview. + * + * @type {Array} */ export const coreDeviceTypes = [ 'Desktop', 'Tablet', 'Mobile' ]; From ee1fba237f879ebad2ddd1427963a37f41929db5 Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Tue, 18 May 2021 22:36:52 +0200 Subject: [PATCH 19/20] Update slotfills docs --- .../slotfills/plugin-preview-menu-item.md | 46 +++++++++++----- .../developers/slotfills/plugin-preview.md | 52 ++++++++++++------- 2 files changed, 68 insertions(+), 30 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 8ff1e899114a8e..fc40135cf9c9a7 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md @@ -1,34 +1,56 @@ # PluginPreviewMenuItem -This is designed to be used alongside the PluginPreview. +Adds a menu item to the "Preview" menu. -- PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. -- PluginPreview: Renders the main content area when that menu item is chosen. +It is designed to be used alongside the `PluginPreview` that renders a custom preview instead of the `VisualEditor` in the block editor. -Each of these takes 2 props, `previewId`, and `children`. +The presence of the `PluginPreview` component is not necessary. +Selecting a preview will not replace the `VisualEditor` with a custom preview in such a case. +Instead, a plugin author may rely on the `onClick` event handler entirely. -- `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. +## Available Props + +- **previewId** `string`: A string identifying the preview. When used, must match across `PluginPreviewMenuItem` and `PluginPreview`. +- **icon** `(string|Element)`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element. +- **onClick** `Function`: Click handler, e.g. for previews that do not register slot fills. ## Example ```js import { registerPlugin } from '@wordpress/plugins'; import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; -import { Fragment } from '@wordpress/element'; +import { external } from '@wordpress/icons'; const PluginPreviewTest = () => ( - + <> - Custom Preview 1 Menu Text + Custom preview 1
-

Custom Preview 1 Content

+

Custom Preview 1 Content

+
+
+ + console.log( event ) } + > + Custom preview 2 + + +
+

Custom Preview 2 Content

-
+ + console.log( event ) } + > + Custom action (no preview) + + ); registerPlugin( 'plugin-preview-test', { diff --git a/docs/designers-developers/developers/slotfills/plugin-preview.md b/docs/designers-developers/developers/slotfills/plugin-preview.md index 021df443584c15..f51ca83ceca5fe 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview.md @@ -1,34 +1,50 @@ # PluginPreview -This is designed to be used alongside the PluginPreviewMenuItem. +Renders the main content area when that menu item is chosen. -- PluginPreviewMenuItem: Adds a menu item to the "Preview" menu. -- PluginPreview: 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. -Each of these takes 2 props, `previewId`, and `children`. +## Available Props -- `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. +- **previewId** `string`: A string identifying the preview. Must match across `PluginPreviewMenuItem` and `PluginPreview`. ## Example ```js import { registerPlugin } from '@wordpress/plugins'; import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; -import { Fragment } from '@wordpress/element'; +import { external } from '@wordpress/icons'; const PluginPreviewTest = () => ( - - - Custom Preview 1 Menu Text - - -
-

Custom Preview 1 Content

-
-
-
+ <> + + Custom preview 1 + + +
+

Custom Preview 1 Content

+
+
+ + console.log( event ) } + > + Custom preview 2 + + +
+

Custom Preview 2 Content

+
+
+ + console.log( event ) } + > + Custom action (no preview) + + ); registerPlugin( 'plugin-preview-test', { From 0301e1d2f60997bee2825f909b4408a31c19c2cf Mon Sep 17 00:00:00 2001 From: Piotr Delawski Date: Mon, 24 May 2021 14:45:12 +0200 Subject: [PATCH 20/20] Do not expose menu item fill; simplify PluginPreview component 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. --- .../slotfills/plugin-preview-menu-item.md | 59 -------------- .../developers/slotfills/plugin-preview.md | 74 ++++++++++-------- docs/reference-guides/slotfills/README.md | 3 +- packages/block-editor/README.md | 29 +++---- packages/block-editor/src/components/index.js | 6 +- .../src/components/plugin-preview/index.js | 78 +++++++++++++++++++ .../src/components/preview-options/index.js | 20 ++--- .../plugin-preview-menu-item/index.js | 54 ------------- .../preview-options/plugin-preview/index.js | 24 ------ packages/block-editor/src/index.js | 3 - .../visual-editor-or-plugin-preview.js | 8 +- 11 files changed, 147 insertions(+), 211 deletions(-) delete mode 100644 docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md create mode 100644 packages/block-editor/src/components/plugin-preview/index.js delete mode 100644 packages/block-editor/src/components/preview-options/plugin-preview-menu-item/index.js delete mode 100644 packages/block-editor/src/components/preview-options/plugin-preview/index.js diff --git a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md b/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md deleted file mode 100644 index fc40135cf9c9a7..00000000000000 --- a/docs/designers-developers/developers/slotfills/plugin-preview-menu-item.md +++ /dev/null @@ -1,59 +0,0 @@ -# PluginPreviewMenuItem - -Adds a menu item to the "Preview" menu. - -It is designed to be used alongside the `PluginPreview` that renders a custom preview instead of the `VisualEditor` in the block editor. - -The presence of the `PluginPreview` component is not necessary. -Selecting a preview will not replace the `VisualEditor` with a custom preview in such a case. -Instead, a plugin author may rely on the `onClick` event handler entirely. - -## Available Props - -- **previewId** `string`: A string identifying the preview. When used, must match across `PluginPreviewMenuItem` and `PluginPreview`. -- **icon** `(string|Element)`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element. -- **onClick** `Function`: Click handler, e.g. for previews that do not register slot fills. - -## Example - -```js -import { registerPlugin } from '@wordpress/plugins'; -import { PluginPreview, PluginPreviewMenuItem } from '@wordpress/block-editor'; -import { external } from '@wordpress/icons'; - -const PluginPreviewTest = () => ( - <> - - Custom preview 1 - - -
-

Custom Preview 1 Content

-
-
- - console.log( event ) } - > - Custom preview 2 - - -
-

Custom Preview 2 Content

-
-
- - console.log( event ) } - > - Custom action (no preview) - - -); - -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 index f51ca83ceca5fe..f950deda2533c9 100644 --- a/docs/designers-developers/developers/slotfills/plugin-preview.md +++ b/docs/designers-developers/developers/slotfills/plugin-preview.md @@ -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 = () => ( - <> - - Custom preview 1 - - -
-

Custom Preview 1 Content

-
-
- - console.log( event ) } - > - Custom preview 2 - - -
-

Custom Preview 2 Content

-
-
- - console.log( event ) } - > - Custom action (no preview) - - + <> + +

+ { __( 'Custom Preview 1 Content' ) } +

+
+ + console.log( event ) } + > +

+ { __( 'Custom Preview 2 Content' ) } +

+
+ + console.log( event ) } + /> + ); -registerPlugin( 'plugin-preview-test', { +registerPlugin( "plugin-preview-test", { render: PluginPreviewTest, } ); ``` diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index bbf0cfe70cc117..4734e347e60303 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -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) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index f428942d6d8d85..051f330718b6c6 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -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 -`` and `` components, and defer to -a `` filled by the plugin to draw the preview. +we are rendering a custom preview registered by the `` +component and defer to a `` filled by the plugin to draw the preview. _Type_ @@ -540,29 +539,21 @@ _Related_ # **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. - -# **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. # **PreserveScrollInReorder** diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index fed9e9752194c7..c3401a4f4a6780 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -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'; diff --git a/packages/block-editor/src/components/plugin-preview/index.js b/packages/block-editor/src/components/plugin-preview/index.js new file mode 100644 index 00000000000000..785f0c012a5518 --- /dev/null +++ b/packages/block-editor/src/components/plugin-preview/index.js @@ -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 ( + <> + + { ( { deviceType, setDeviceType } ) => ( + { + if ( name && previewSlot.fills?.length > 0 ) { + setDeviceType( name ); + } + if ( onClick ) { + onClick( ...args ); + } + } } + icon={ icon || ( deviceType === name && check ) } + { ...props } + > + { title } + + ) } + + { children && { children } } + + ); +} diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js index 44e0d8b540d137..060e33455fd80e 100644 --- a/packages/block-editor/src/components/preview-options/index.js +++ b/packages/block-editor/src/components/preview-options/index.js @@ -9,7 +9,6 @@ import classnames from 'classnames'; import { useViewportMatch } from '@wordpress/compose'; import { __experimentalUseSlot as useSlot, - createSlotFill, DropdownMenu, MenuGroup, MenuItem, @@ -17,12 +16,10 @@ import { 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 @@ -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 - * `` and `` components, and defer to - * a `` filled by the plugin to draw the preview. + * we are rendering a custom preview registered by the `` + * component and defer to a `` filled by the plugin to draw the preview. * * @type {Array} */ @@ -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; @@ -99,7 +95,7 @@ export default function PreviewOptions( { - { slot?.fills?.length && ( + { previewMenuSlot.fills?.length > 0 && ( - { ( { deviceType, setDeviceType } ) => ( - { - if ( previewId ) { - setDeviceType( previewId ); - } - if ( onClick ) { - onClick( ...args ); - } - } } - icon={ icon || ( deviceType === previewId && check ) } - { ...props } - > - { 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 deleted file mode 100644 index f2ec6784432da7..00000000000000 --- a/packages/block-editor/src/components/preview-options/plugin-preview/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * WordPress dependencies - */ -import { Fill } from '@wordpress/components'; - -/** - * 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 } - - ); -} diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index 6e014b740a7861..2720c2cd4c9588 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -14,6 +14,3 @@ export * from './components'; export * from './utils'; export { storeConfig, store } 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/visual-editor/visual-editor-or-plugin-preview.js b/packages/edit-post/src/components/visual-editor/visual-editor-or-plugin-preview.js index 1146a4dca5d88a..dadf43021a0308 100644 --- 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 @@ -21,11 +21,11 @@ function VisualEditorOrPluginPreview( props ) { select( editPostStore ).__experimentalGetPreviewDeviceType(), [] ); - const slotName = `core/block-editor/plugin-preview/${ previewId }`; - const slot = useSlot( slotName ); + const previewSlotName = `core/block-editor/plugin-preview/${ previewId }`; + const previewSlot = useSlot( previewSlotName ); - if ( slot?.fills?.length > 0 ) { - return ; + if ( previewSlot.fills?.length > 0 ) { + return ; } return ;