-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Site Editor - add basic plugin support #34460
Changes from all commits
7ca04ff
8491381
6b582f4
e10392a
c65e557
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { ActionItem } from '@wordpress/interface'; | ||
import { compose } from '@wordpress/compose'; | ||
import { withPluginContext } from '@wordpress/plugins'; | ||
|
||
/** | ||
* Renders a menu item in `Plugins` group in `More Menu` drop down, and can be used to 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 then the menu item is represented as an anchor rather than button. It corresponds to the `href` attribute of the anchor. | ||
* @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. | ||
* @param {Function} [props.onClick=noop] 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 [Button](/packages/components/src/button/README.md) component. | ||
* | ||
* @example | ||
* ```js | ||
* // Using ES5 syntax | ||
* var __ = wp.i18n.__; | ||
* var PluginMoreMenuItem = wp.editSite.PluginMoreMenuItem; | ||
* var moreIcon = wp.element.createElement( 'svg' ); //... svg element. | ||
* | ||
* function onButtonClick() { | ||
* alert( 'Button clicked.' ); | ||
* } | ||
* | ||
* function MyButtonMoreMenuItem() { | ||
* return wp.element.createElement( | ||
* PluginMoreMenuItem, | ||
* { | ||
* icon: moreIcon, | ||
* onClick: onButtonClick, | ||
* }, | ||
* __( 'My button title' ) | ||
* ); | ||
* } | ||
* ``` | ||
* | ||
* @example | ||
* ```jsx | ||
* // Using ESNext syntax | ||
* import { __ } from '@wordpress/i18n'; | ||
* import { PluginMoreMenuItem } from '@wordpress/edit-site'; | ||
* import { more } from '@wordpress/icons'; | ||
* | ||
* function onButtonClick() { | ||
* alert( 'Button clicked.' ); | ||
* } | ||
* | ||
* const MyButtonMoreMenuItem = () => ( | ||
* <PluginMoreMenuItem | ||
* icon={ more } | ||
* onClick={ onButtonClick } | ||
* > | ||
* { __( 'My button title' ) } | ||
* </PluginMoreMenuItem> | ||
* ); | ||
* ``` | ||
* | ||
* @return {WPComponent} The component to be rendered. | ||
*/ | ||
export default compose( | ||
withPluginContext( ( context, ownProps ) => { | ||
return { | ||
icon: ownProps.icon || context.icon, | ||
name: 'core/edit-site/plugin-more-menu', | ||
}; | ||
} ) | ||
)( ActionItem ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { ComplementaryAreaMoreMenuItem } from '@wordpress/interface'; | ||
|
||
/** | ||
* Renders a menu item in `Plugins` group in `More Menu` drop down, | ||
* and can be used to activate the corresponding `PluginSidebar` component. | ||
* The text within the component appears as the menu item label. | ||
* | ||
* @param {Object} props Component props. | ||
* @param {string} props.target A string identifying the target sidebar you wish to be activated by this menu item. Must be the same as the `name` prop you have given to that sidebar. | ||
* @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. | ||
* | ||
* @example | ||
* ```js | ||
* // Using ES5 syntax | ||
* var __ = wp.i18n.__; | ||
* var PluginSidebarMoreMenuItem = wp.editSite.PluginSidebarMoreMenuItem; | ||
* var moreIcon = wp.element.createElement( 'svg' ); //... svg element. | ||
* | ||
* function MySidebarMoreMenuItem() { | ||
* return wp.element.createElement( | ||
* PluginSidebarMoreMenuItem, | ||
* { | ||
* target: 'my-sidebar', | ||
* icon: moreIcon, | ||
* }, | ||
* __( 'My sidebar title' ) | ||
* ) | ||
* } | ||
* ``` | ||
* | ||
* @example | ||
* ```jsx | ||
* // Using ESNext syntax | ||
* import { __ } from '@wordpress/i18n'; | ||
* import { PluginSidebarMoreMenuItem } from '@wordpress/edit-site'; | ||
* import { more } from '@wordpress/icons'; | ||
* | ||
* const MySidebarMoreMenuItem = () => ( | ||
* <PluginSidebarMoreMenuItem | ||
* target="my-sidebar" | ||
* icon={ more } | ||
* > | ||
* { __( 'My sidebar title' ) } | ||
* </PluginSidebarMoreMenuItem> | ||
* ); | ||
* ``` | ||
* | ||
* @return {WPComponent} The component to be rendered. | ||
*/ | ||
|
||
export default function PluginSidebarMoreMenuItem( props ) { | ||
return ( | ||
<ComplementaryAreaMoreMenuItem | ||
// Menu item is marked with unstable prop for backward compatibility. | ||
// @see https://github.com/WordPress/gutenberg/issues/14457 | ||
__unstableExplicitMenuItem | ||
scope="core/edit-site" | ||
{ ...props } | ||
/> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { ComplementaryArea } from '@wordpress/interface'; | ||
|
||
/** | ||
* 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: | ||
* | ||
* ```js | ||
* wp.data.dispatch( 'core/edit-site' ).openGeneralSidebar( 'plugin-name/sidebar-name' ); | ||
* ``` | ||
* | ||
* @see PluginSidebarMoreMenuItem | ||
* | ||
* @param {Object} props Element props. | ||
* @param {string} props.name A string identifying the sidebar. Must be unique for every sidebar registered within the scope of your plugin. | ||
* @param {string} [props.className] An optional class name added to the sidebar body. | ||
* @param {string} props.title Title displayed at the top of the sidebar. | ||
* @param {boolean} [props.isPinnable=true] Whether to allow to pin sidebar to the toolbar. When set to `true` it also automatically renders a corresponding menu item. | ||
* @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. | ||
* | ||
* @example | ||
* ```js | ||
* // Using ES5 syntax | ||
* var __ = wp.i18n.__; | ||
* var el = wp.element.createElement; | ||
* var PanelBody = wp.components.PanelBody; | ||
* var PluginSidebar = wp.editSite.PluginSidebar; | ||
* var moreIcon = wp.element.createElement( 'svg' ); //... svg element. | ||
* | ||
* function MyPluginSidebar() { | ||
* return el( | ||
* PluginSidebar, | ||
* { | ||
* name: 'my-sidebar', | ||
* title: 'My sidebar title', | ||
* icon: moreIcon, | ||
* }, | ||
* el( | ||
* PanelBody, | ||
* {}, | ||
* __( 'My sidebar content' ) | ||
* ) | ||
* ); | ||
* } | ||
* ``` | ||
* | ||
* @example | ||
* ```jsx | ||
* // Using ESNext syntax | ||
* import { __ } from '@wordpress/i18n'; | ||
* import { PanelBody } from '@wordpress/components'; | ||
* import { PluginSidebar } from '@wordpress/edit-site'; | ||
* import { more } from '@wordpress/icons'; | ||
* | ||
* const MyPluginSidebar = () => ( | ||
* <PluginSidebar | ||
* name="my-sidebar" | ||
* title="My sidebar title" | ||
* icon={ more } | ||
* > | ||
* <PanelBody> | ||
* { __( 'My sidebar content' ) } | ||
* </PanelBody> | ||
* </PluginSidebar> | ||
* ); | ||
* ``` | ||
*/ | ||
export default function PluginSidebarEditSite( { className, ...props } ) { | ||
return ( | ||
<ComplementaryArea | ||
panelClassName={ className } | ||
className="edit-site-sidebar" | ||
scope="core/edit-site" | ||
{ ...props } | ||
/> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ import { addQueryArgs, getPathAndQueryString } from '@wordpress/url'; | |
import { __ } from '@wordpress/i18n'; | ||
import { store as noticesStore } from '@wordpress/notices'; | ||
import { store as coreStore } from '@wordpress/core-data'; | ||
import { store as interfaceStore } from '@wordpress/interface'; | ||
|
||
/** | ||
* Internal dependencies | ||
|
@@ -441,3 +442,31 @@ export function* revertTemplate( template ) { | |
); | ||
} | ||
} | ||
/** | ||
* Returns an action object used in signalling that the user opened an editor sidebar. | ||
* | ||
* @param {?string} name Sidebar name to be opened. | ||
* | ||
* @yield {Object} Action object. | ||
*/ | ||
export function* openGeneralSidebar( name ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Does this need to be handled as a control effect because it's dispatching to a separate store? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we use controls.dispatch to send this over to the interfaceStore as is done with the equivalent actions in the edit-post store. Or were you proposing a different approach here? |
||
yield controls.dispatch( | ||
interfaceStore, | ||
'enableComplementaryArea', | ||
editSiteStoreName, | ||
name | ||
); | ||
} | ||
|
||
/** | ||
* Returns an action object signalling that the user closed the sidebar. | ||
* | ||
* @yield {Object} Action object. | ||
*/ | ||
export function* closeGeneralSidebar() { | ||
yield controls.dispatch( | ||
interfaceStore, | ||
'disableComplementaryArea', | ||
editSiteStoreName | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a note that I looked into the implications of taking
__unstableExplicitMenuItem
out, since there won't be a concern with backwards compatibility, as we're just adding this to the Site Editor now.If this attribute was removed,
PluginSidebar
components can't register a companionPluginSidebarMoreMenuItem
whenisPinnable={ true }
. ThePluginSidebarMoreMenuItem
is generated automatically in that case, and is duplicated if it's also declared manually.I think it's best to leave
__unstableExplicitMenuItem
in place:PluginSidebarMoreMenuItem
is declared, it is used as thePluginSidebar
's menu item whetherisPinnable
is set totrue
orfalse
, which seems less confusing, overall