Skip to content

Commit

Permalink
Editor: Add extensibility to PreviewOptions v2 (#64644)
Browse files Browse the repository at this point in the history
* add plugin-preview-dropdown-item

* Add slot

* export PluginPreviewDropdownItem

* add registerPlugin example

Co-authored-by: Greg Ziółkowski <[email protected]>

* example import from @wordpress/editor

Co-authored-by: Greg Ziółkowski <[email protected]>

* rename to PluginPreviewMenuItem

* add tests

tests

---------

Co-authored-by: Greg Ziółkowski <[email protected]>

Co-authored-by: lezama <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: gziolo <[email protected]>
Co-authored-by: simison <[email protected]>
Co-authored-by: fabiankaegy <[email protected]>
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: fumikito <[email protected]>
Co-authored-by: westonruter <[email protected]>
  • Loading branch information
9 people authored Sep 3, 2024
1 parent 9c62555 commit 9d4f918
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 0 deletions.
13 changes: 13 additions & 0 deletions packages/e2e-tests/plugins/plugins-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ function enqueue_plugins_api_plugin_scripts() {
filemtime( plugin_dir_path( __FILE__ ) . 'plugins-api/document-setting.js' ),
true
);

wp_enqueue_script(
'gutenberg-test-plugins-api-preview-menu',
plugins_url( 'plugins-api/preview-menu.js', __FILE__ ),
array(
'wp-editor',
'wp-element',
'wp-i18n',
'wp-plugins',
),
filemtime( plugin_dir_path( __FILE__ ) . 'plugins-api/preview-menu.js' ),
true
);
}

add_action( 'init', 'enqueue_plugins_api_plugin_scripts' );
14 changes: 14 additions & 0 deletions packages/e2e-tests/plugins/plugins-api/preview-menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
( function () {
const { __ } = wp.i18n;
const { registerPlugin } = wp.plugins;
const PluginPreviewMenuItem = wp.editor.PluginPreviewMenuItem;
const el = wp.element.createElement;

function CustomPreviewMenuItem() {
return el( PluginPreviewMenuItem, {}, __( 'Custom Preview' ) );
}

registerPlugin( 'custom-preview-menu-item', {
render: CustomPreviewMenuItem,
} );
} )();
37 changes: 37 additions & 0 deletions packages/editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,43 @@ _Returns_

- `Component`: The component to be rendered.

### PluginPreviewMenuItem

Renders a menu item in the Preview dropdown, which can be used as a button or link depending on the props provided. The text within the component appears as the menu item label.

_Usage_

```jsx
import { __ } from '@wordpress/i18n';
import { PluginPreviewMenuItem } from '@wordpress/editor';
import { external } from '@wordpress/icons';

function onPreviewClick() {
// Handle preview action
}

const ExternalPreviewMenuItem = () => (
<PreviewDropdownMenuItem icon={ external } onClick={ onPreviewClick }>
{ __( 'Preview in new tab' ) }
</PreviewDropdownMenuItem>
);
registerPlugin( 'external-preview-menu-item', {
render: ExternalPreviewMenuItem,
} );
```

_Parameters_

- _props_ `Object`: Component properties.
- _props.href_ `[string]`: When `href` is provided, the menu item is rendered as an anchor instead of a button. It corresponds to the `href` attribute of the anchor.
- _props.icon_ `[WPBlockTypeIconRender]`: The icon to be rendered to the left of the menu item label. Can be a Dashicon slug or an SVG WP element.
- _props.onClick_ `[Function]`: The callback function to be executed when the user clicks the menu item.
- _props.other_ `[...*]`: Any additional props are passed through to the underlying MenuItem component.

_Returns_

- `Component`: The rendered menu item component.

### PluginSidebar

Renders a sidebar when activated. The contents within the `PluginSidebar` will appear as content within the sidebar. It also automatically renders a corresponding `PluginSidebarMenuItem` component when `isPinnable` flag is set to `true`. If you wish to display the sidebar, you can with use the `PluginSidebarMoreMenuItem` component or the `wp.data.dispatch` API:
Expand Down
1 change: 1 addition & 0 deletions packages/editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export { default as PluginMoreMenuItem } from './plugin-more-menu-item';
export { default as PluginPostPublishPanel } from './plugin-post-publish-panel';
export { default as PluginPostStatusInfo } from './plugin-post-status-info';
export { default as PluginPrePublishPanel } from './plugin-pre-publish-panel';
export { default as PluginPreviewMenuItem } from './plugin-preview-menu-item';
export { default as PluginSidebar } from './plugin-sidebar';
export { default as PluginSidebarMoreMenuItem } from './plugin-sidebar-more-menu-item';
export { default as PostTemplatePanel } from './post-template/panel';
Expand Down
52 changes: 52 additions & 0 deletions packages/editor/src/components/plugin-preview-menu-item/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* WordPress dependencies
*/
import { compose } from '@wordpress/compose';
import { MenuItem } from '@wordpress/components';
import { withPluginContext } from '@wordpress/plugins';
import { ActionItem } from '@wordpress/interface';

/**
* Renders a menu item in the Preview dropdown, which can be used as a button or link depending on the props provided.
* The text within the component appears as the menu item label.
*
* @param {Object} props Component properties.
* @param {string} [props.href] When `href` is provided, the menu item is rendered as an anchor instead of a button. It corresponds to the `href` attribute of the anchor.
* @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The icon to be rendered to the left of the menu item label. Can be a Dashicon slug or an SVG WP element.
* @param {Function} [props.onClick] The callback function to be executed when the user clicks the menu item.
* @param {...*} [props.other] Any additional props are passed through to the underlying MenuItem component.
*
* @example
* ```jsx
* import { __ } from '@wordpress/i18n';
* import { PluginPreviewMenuItem } from '@wordpress/editor';
* import { external } from '@wordpress/icons';
*
* function onPreviewClick() {
* // Handle preview action
* }
*
* const ExternalPreviewMenuItem = () => (
* <PreviewDropdownMenuItem
* icon={ external }
* onClick={ onPreviewClick }
* >
* { __( 'Preview in new tab' ) }
* </PreviewDropdownMenuItem>
* );
* registerPlugin( 'external-preview-menu-item', {
* render: ExternalPreviewMenuItem,
* } );
* ```
*
* @return {Component} The rendered menu item component.
*/
export default compose(
withPluginContext( ( context, ownProps ) => {
return {
as: ownProps.as ?? MenuItem,
icon: ownProps.icon || context.icon,
name: 'core/plugin-preview-menu',
};
} )
)( ActionItem );
6 changes: 6 additions & 0 deletions packages/editor/src/components/preview-dropdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { store as coreStore } from '@wordpress/core-data';
import { useEffect, useRef } from '@wordpress/element';
import { store as preferencesStore } from '@wordpress/preferences';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { ActionItem } from '@wordpress/interface';

/**
* Internal dependencies
Expand Down Expand Up @@ -206,6 +207,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
/>
</MenuGroup>
) }
<ActionItem.Slot
name="core/plugin-preview-menu"
as={ MenuGroup }
fillProps={ { onClick: onClose } }
/>
</>
) }
</DropdownMenu>
Expand Down
21 changes: 21 additions & 0 deletions test/e2e/specs/editor/plugins/plugins-api.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,25 @@ test.describe( 'Plugins API', () => {
).toBeVisible();
} );
} );

test.describe( 'Preview Menu Item', () => {
test( 'Should render and interact with PluginPreviewMenuItem', async ( {
page,
} ) => {
await page
.getByRole( 'region', { name: 'Editor top bar' } )
.locator( '.editor-preview-dropdown__toggle' )
.click();

const customPreviewItem = page.getByRole( 'menuitem', {
name: 'Custom Preview',
} );

await expect( customPreviewItem ).toBeVisible();

await customPreviewItem.click();

await expect( customPreviewItem ).toBeHidden();
} );
} );
} );

0 comments on commit 9d4f918

Please sign in to comment.