Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor: Add extensibility to PreviewOptions v2 #64644

Merged
merged 7 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
} );
} );
} );
Loading