Skip to content

Commit

Permalink
Publish types for plugins package (#49649)
Browse files Browse the repository at this point in the history
* Publish types for the plugins package
  • Loading branch information
noahtallen authored Apr 20, 2023
1 parent 51cf8e8 commit dc83cf6
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 58 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- `Modal`: Increased border radius ([#49870](https://github.com/WordPress/gutenberg/pull/49870)).
- `Modal`: Updated spacing / dimensions of `isFullScreen` ([#49894](https://github.com/WordPress/gutenberg/pull/49894)).
- `SlotFill`: Added util for creating private SlotFills and supporting Symbol keys ([#49819](https://github.com/WordPress/gutenberg/pull/49819)).

- `IconType`: Export for external use ([#49649](https://github.com/WordPress/gutenberg/pull/49649)).

### Documentation

Expand Down
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export { default as GuidePage } from './guide/page';
export { Heading as __experimentalHeading } from './heading';
export { HStack as __experimentalHStack } from './h-stack';
export { default as Icon } from './icon';
export type { IconType } from './icon';
export { default as IconButton } from './button/deprecated';
export {
ItemGroup as __experimentalItemGroup,
Expand Down
6 changes: 3 additions & 3 deletions packages/is-shallow-equal/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export { default as isShallowEqualArrays } from './arrays';

/**
* Returns true if the two arrays or objects are shallow equal, or false
* otherwise.
* otherwise. Also handles primitive values, just in case.
*
* @param {any[]|ComparableObject} a First object or array to compare.
* @param {any[]|ComparableObject} b Second object or array to compare.
* @param {unknown} a First object or array to compare.
* @param {unknown} b Second object or array to compare.
*
* @return {boolean} Whether the two values are shallow equal.
*/
Expand Down
4 changes: 4 additions & 0 deletions packages/plugins/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Publish types for `@wordpress/plugins` ([#49649](https://github.com/WordPress/gutenberg/pull/49649))

## 5.8.0 (2023-04-12)

## 5.7.0 (2023-03-29)
Expand Down
18 changes: 9 additions & 9 deletions packages/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ _Parameters_

_Returns_

- `?WPPlugin`: Plugin setting.
- `WPPlugin | undefined`: Plugin setting.

#### getPlugins

Returns all registered plugins without a scope or for a given scope.

_Parameters_

- _scope_ `[string]`: The scope to be used when rendering inside a plugin area. No scope by default.
- _scope_ `string`: The scope to be used when rendering inside a plugin area. No scope by default.

_Returns_

Expand Down Expand Up @@ -70,9 +70,9 @@ const Layout = () => (

_Parameters_

- _props_ `Object`:
- _props.scope_ `string|undefined`:
- _props.onError_ `Function|undefined`:
- _props_ `{ scope?: string; onError?: ( name: WPPlugin[ 'name' ], error: Error ) => void; }`:
- _props.scope_ `string`:
- _props.onError_ `( name: WPPlugin[ 'name' ], error: Error ) => void`:

_Returns_

Expand Down Expand Up @@ -147,12 +147,12 @@ registerPlugin( 'plugin-name', {

_Parameters_

- _name_ `string`: A string identifying the plugin.Must be unique across all registered plugins.
- _settings_ `Omit<WPPlugin, 'name'>`: The settings for this plugin.
- _name_ `string`: A string identifying the plugin. Must be unique across all registered plugins.
- _settings_ `PluginSettings`: The settings for this plugin.

_Returns_

- `WPPlugin`: The final plugin settings object.
- `PluginSettings | null`: The final plugin settings object.

#### unregisterPlugin

Expand Down Expand Up @@ -188,7 +188,7 @@ A Higher Order Component used to inject Plugin context to the wrapped component.

_Parameters_

- _mapContextToProps_ `Function`: Function called on every context change, expected to return object of props to merge with the component's own props.
- _mapContextToProps_ `( context: PluginContext, props: T ) => T & PluginContext`: Function called on every context change, expected to return object of props to merge with the component's own props.

_Returns_

Expand Down
2 changes: 2 additions & 0 deletions packages/plugins/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
"main": "build/index.js",
"module": "build-module/index.js",
"react-native": "src/index",
"types": "build-types",
"dependencies": {
"@babel/runtime": "^7.16.0",
"@wordpress/components": "file:../components",
"@wordpress/compose": "file:../compose",
"@wordpress/element": "file:../element",
"@wordpress/hooks": "file:../hooks",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,50 @@
*/
import { applyFilters, doAction } from '@wordpress/hooks';
import { plugins as pluginsIcon } from '@wordpress/icons';
import type { IconType } from '@wordpress/components';
import type { WPComponent } from '@wordpress/element';

/**
* Defined behavior of a plugin type.
*
* @typedef {Object} WPPlugin
*
* @property {string} name A string identifying the plugin. Must be
* unique across all registered plugins.
* @property {string|WPElement|Function} [icon] An icon to be shown in the UI. It can
* be a slug of the Dashicon, or an element
* (or function returning an element) if you
* choose to render your own SVG.
* @property {Function} render A component containing the UI elements
* to be rendered.
* @property {string} [scope] The optional scope to be used when rendering inside
* a plugin area. No scope by default.
*/
export interface WPPlugin {
/**
* A string identifying the plugin. Must be unique across all registered plugins.
*/
name: string;

/**
* An icon to be shown in the UI. It can be a slug of the Dashicon, or an
* element (or function returning an element) if you choose to render your
* own SVG.
*/
icon?: IconType;

/**
* A component containing the UI elements to be rendered.
*/
render: WPComponent;

/**
* The optional scope to be used when rendering inside a plugin area.
* No scope by default.
*/
scope?: string;
}

type PluginSettings = Omit< WPPlugin, 'name' >;

/**
* Plugin definitions keyed by plugin name.
*
* @type {Object.<string,WPPlugin>}
*/
const plugins = {};
const plugins = {} as Record< string, WPPlugin >;

/**
* Registers a plugin to the editor.
*
* @param {string} name A string identifying the plugin.Must be
* unique across all registered plugins.
* @param {Omit<WPPlugin, 'name'>} settings The settings for this plugin.
* @param name A string identifying the plugin. Must be
* unique across all registered plugins.
* @param settings The settings for this plugin.
*
* @example
* ```js
Expand Down Expand Up @@ -105,9 +118,12 @@ const plugins = {};
* } );
* ```
*
* @return {WPPlugin} The final plugin settings object.
* @return The final plugin settings object.
*/
export function registerPlugin( name, settings ) {
export function registerPlugin(
name: string,
settings: PluginSettings
): PluginSettings | null {
if ( typeof settings !== 'object' ) {
console.error( 'No settings object provided!' );
return null;
Expand All @@ -126,7 +142,11 @@ export function registerPlugin( name, settings ) {
console.error( `Plugin "${ name }" is already registered.` );
}

settings = applyFilters( 'plugins.registerPlugin', settings, name );
settings = applyFilters(
'plugins.registerPlugin',
settings,
name
) as PluginSettings;

const { render, scope } = settings;

Expand Down Expand Up @@ -165,7 +185,7 @@ export function registerPlugin( name, settings ) {
/**
* Unregisters a plugin by name.
*
* @param {string} name Plugin name.
* @param name Plugin name.
*
* @example
* ```js
Expand All @@ -183,10 +203,10 @@ export function registerPlugin( name, settings ) {
* unregisterPlugin( 'plugin-name' );
* ```
*
* @return {WPPlugin | undefined} The previous plugin settings object, if it has been
* successfully unregistered; otherwise `undefined`.
* @return The previous plugin settings object, if it has been
* successfully unregistered; otherwise `undefined`.
*/
export function unregisterPlugin( name ) {
export function unregisterPlugin( name: string ): WPPlugin | undefined {
if ( ! plugins[ name ] ) {
console.error( 'Plugin "' + name + '" is not registered.' );
return;
Expand All @@ -202,23 +222,23 @@ export function unregisterPlugin( name ) {
/**
* Returns a registered plugin settings.
*
* @param {string} name Plugin name.
* @param name Plugin name.
*
* @return {?WPPlugin} Plugin setting.
* @return Plugin setting.
*/
export function getPlugin( name ) {
export function getPlugin( name: string ): WPPlugin | undefined {
return plugins[ name ];
}

/**
* Returns all registered plugins without a scope or for a given scope.
*
* @param {string} [scope] The scope to be used when rendering inside
* a plugin area. No scope by default.
* @param scope The scope to be used when rendering inside
* a plugin area. No scope by default.
*
* @return {WPPlugin[]} The list of plugins without a scope or for a given scope.
* @return The list of plugins without a scope or for a given scope.
*/
export function getPlugins( scope ) {
export function getPlugins( scope?: string ): WPPlugin[] {
return Object.values( plugins ).filter(
( plugin ) => plugin.scope === scope
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,22 @@ import isShallowEqual from '@wordpress/is-shallow-equal';
import { PluginContextProvider } from '../plugin-context';
import { PluginErrorBoundary } from '../plugin-error-boundary';
import { getPlugins } from '../../api';
import type { PluginContext } from '../plugin-context';
import type { WPPlugin } from '../../api';

const getPluginContext = memoize( ( icon, name ) => ( { icon, name } ) );
const getPluginContext = memoize(
( icon: PluginContext[ 'icon' ], name: PluginContext[ 'name' ] ) => ( {
icon,
name,
} )
);

/**
* A component that renders all plugin fills in a hidden div.
*
* @param {Object} props
* @param {string|undefined} props.scope
* @param {Function|undefined} props.onError
* @param props
* @param props.scope
* @param props.onError
* @example
* ```js
* // Using ES5 syntax
Expand Down Expand Up @@ -56,12 +63,23 @@ const getPluginContext = memoize( ( icon, name ) => ( { icon, name } ) );
*
* @return {WPComponent} The component to be rendered.
*/
function PluginArea( { scope, onError } ) {
function PluginArea( {
scope,
onError,
}: {
scope?: string;
onError?: ( name: WPPlugin[ 'name' ], error: Error ) => void;
} ) {
const store = useMemo( () => {
let lastValue;
let lastValue: WPPlugin[] = [];

return {
subscribe( listener ) {
subscribe(
listener: (
plugin: Omit< WPPlugin, 'name' >,
name: WPPlugin[ 'name' ]
) => void
) {
addAction(
'plugins.pluginRegistered',
'core/plugins/plugin-area/plugins-registered',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
import { createContext } from '@wordpress/element';
import { createHigherOrderComponent } from '@wordpress/compose';

const { Consumer, Provider } = createContext( {
/**
* Internal dependencies
*/
import type { WPPlugin } from '../../api';

export interface PluginContext {
name: null | WPPlugin[ 'name' ];
icon: null | WPPlugin[ 'icon' ];
}

const { Consumer, Provider } = createContext< PluginContext >( {
name: null,
icon: null,
} );
Expand All @@ -15,13 +25,18 @@ export { Provider as PluginContextProvider };
* A Higher Order Component used to inject Plugin context to the
* wrapped component.
*
* @param {Function} mapContextToProps Function called on every context change,
* expected to return object of props to
* merge with the component's own props.
* @param mapContextToProps Function called on every context change,
* expected to return object of props to
* merge with the component's own props.
*
* @return {WPComponent} Enhanced component with injected context as props.
*/
export const withPluginContext = ( mapContextToProps ) =>
export const withPluginContext = (
mapContextToProps: < T >(
context: PluginContext,
props: T
) => T & PluginContext
) =>
createHigherOrderComponent( ( OriginalComponent ) => {
return ( props ) => (
<Consumer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import { Component } from '@wordpress/element';

export class PluginErrorBoundary extends Component {
/**
* @param {Object} props
*/
constructor( props ) {
super( props );
this.state = {
Expand All @@ -15,6 +18,9 @@ export class PluginErrorBoundary extends Component {
return { hasError: true };
}

/**
* @param {Error} error Error object passed by React.
*/
componentDidCatch( error ) {
const { name, onError } = this.props;
if ( onError ) {
Expand Down
Loading

1 comment on commit dc83cf6

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in dc83cf6.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4758790379
📝 Reported issues:

Please sign in to comment.