@wordpress/data
Version:
Data module for WordPress.
169 lines (159 loc) • 4.57 kB
text/typescript
/**
* Internal dependencies
*/
import { createRegistryControl } from './factory';
import type { StoreDescriptor } from './types';
const SELECT = '@@data/SELECT';
const RESOLVE_SELECT = '@@data/RESOLVE_SELECT';
const DISPATCH = '@@data/DISPATCH';
function isStoreDescriptor( object: unknown ): object is StoreDescriptor {
return object !== null && typeof object === 'object';
}
/**
* Dispatches a control action for triggering a synchronous registry select.
*
* Note: This control synchronously returns the current selector value, triggering the
* resolution, but not waiting for it.
*
* @param storeNameOrDescriptor Unique namespace identifier for the store
* @param selectorName The name of the selector.
* @param args Arguments for the selector.
*
* @example
* ```js
* import { controls } from '@wordpress/data';
*
* // Action generator using `select`.
* export function* myAction() {
* const isEditorSideBarOpened = yield controls.select( 'core/edit-post', 'isEditorSideBarOpened' );
* // Do stuff with the result from the `select`.
* }
* ```
*
* @return The control descriptor.
*/
function select(
storeNameOrDescriptor: string | StoreDescriptor,
selectorName: string,
...args: unknown[]
) {
return {
type: SELECT,
storeKey: isStoreDescriptor( storeNameOrDescriptor )
? storeNameOrDescriptor.name
: storeNameOrDescriptor,
selectorName,
args,
};
}
/**
* Dispatches a control action for triggering and resolving a registry select.
*
* Note: when this control action is handled, it automatically considers
* selectors that may have a resolver. In such case, it will return a `Promise` that resolves
* after the selector finishes resolving, with the final result value.
*
* @param storeNameOrDescriptor Unique namespace identifier for the store
* @param selectorName The name of the selector
* @param args Arguments for the selector.
*
* @example
* ```js
* import { controls } from '@wordpress/data';
*
* // Action generator using resolveSelect
* export function* myAction() {
* const isSidebarOpened = yield controls.resolveSelect( 'core/edit-post', 'isEditorSideBarOpened' );
* // do stuff with the result from the select.
* }
* ```
*
* @return The control descriptor.
*/
function resolveSelect(
storeNameOrDescriptor: string | StoreDescriptor< any >,
selectorName: string,
...args: any[]
) {
return {
type: RESOLVE_SELECT,
storeKey: isStoreDescriptor( storeNameOrDescriptor )
? storeNameOrDescriptor.name
: storeNameOrDescriptor,
selectorName,
args,
};
}
/**
* Dispatches a control action for triggering a registry dispatch.
*
* @param storeNameOrDescriptor Unique namespace identifier for the store
* @param actionName The name of the action to dispatch
* @param args Arguments for the dispatch action.
*
* @example
* ```js
* import { controls } from '@wordpress/data-controls';
*
* // Action generator using dispatch
* export function* myAction() {
* yield controls.dispatch( 'core/editor', 'togglePublishSidebar' );
* // do some other things.
* }
* ```
*
* @return The control descriptor.
*/
function dispatch(
storeNameOrDescriptor: string | StoreDescriptor,
actionName: string,
...args: unknown[]
) {
return {
type: DISPATCH,
storeKey: isStoreDescriptor( storeNameOrDescriptor )
? storeNameOrDescriptor.name
: storeNameOrDescriptor,
actionName,
args,
};
}
export const controls = { select, resolveSelect, dispatch };
type SelectorControlArgs = {
storeKey: string;
selectorName: string;
args: unknown[];
};
type ActionControlArgs = {
storeKey: string;
actionName: string;
args: unknown[];
};
export const builtinControls = {
[ SELECT ]: createRegistryControl(
( registry ) =>
( { storeKey, selectorName, args }: SelectorControlArgs ) =>
registry.select( storeKey )[ selectorName ]( ...args )
),
[ RESOLVE_SELECT ]: createRegistryControl(
( registry ) =>
( { storeKey, selectorName, args }: SelectorControlArgs ) => {
const selector = registry.select( storeKey )[
selectorName
] as ( ( ...a: any[] ) => any ) & {
hasResolver?: boolean;
};
const method = selector.hasResolver
? 'resolveSelect'
: 'select';
return registry[ method ]( storeKey )[ selectorName ](
...args
);
}
),
[ DISPATCH ]: createRegistryControl(
( registry ) =>
( { storeKey, actionName, args }: ActionControlArgs ) =>
registry.dispatch( storeKey )[ actionName ]( ...args )
),
};