@wordpress/components
Version:
UI components for WordPress.
136 lines (103 loc) • 4.32 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.contextConnect = contextConnect;
exports.getConnectNamespace = getConnectNamespace;
exports.hasConnectNamespace = hasConnectNamespace;
var _lodash = require("lodash");
var _element = require("@wordpress/element");
var _warning = _interopRequireDefault(require("@wordpress/warning"));
var _constants = require("./constants");
var _getStyledClassNameFromKey = require("./get-styled-class-name-from-key");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/* eslint-disable jsdoc/valid-types */
/**
* Forwards ref (React.ForwardRef) and "Connects" (or registers) a component
* within the Context system under a specified namespace.
*
* This is an (experimental) evolution of the initial connect() HOC.
* The hope is that we can improve render performance by removing functional
* component wrappers.
*
* @template {import('./polymorphic-component').ViewOwnProps<{}, any>} P
* @param {(props: P, ref: import('react').Ref<any>) => JSX.Element | null} Component The component to register into the Context system.
* @param {string} namespace The namespace to register the component under.
* @param {Object} options
* @param {boolean} [options.memo=false]
* @return {import('./polymorphic-component').PolymorphicComponent<import('./polymorphic-component').ElementTypeFromViewOwnProps<P>, import('./polymorphic-component').PropsFromViewOwnProps<P>>} The connected PolymorphicComponent
*/
function contextConnect(Component, namespace, options = {}) {
/* eslint-enable jsdoc/valid-types */
const {
memo: memoProp = false
} = options;
let WrappedComponent = (0, _element.forwardRef)(Component);
if (memoProp) {
// @ts-ignore
WrappedComponent = (0, _element.memo)(WrappedComponent);
}
if (typeof namespace === 'undefined') {
typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? (0, _warning.default)('contextConnect: Please provide a namespace') : void 0;
} // @ts-ignore internal property
let mergedNamespace = WrappedComponent[_constants.CONNECT_STATIC_NAMESPACE] || [namespace];
/**
* Consolidate (merge) namespaces before attaching it to the WrappedComponent.
*/
if (Array.isArray(namespace)) {
mergedNamespace = [...mergedNamespace, ...namespace];
}
if (typeof namespace === 'string') {
mergedNamespace = [...mergedNamespace, namespace];
}
WrappedComponent.displayName = namespace; // @ts-ignore internal property
WrappedComponent[_constants.CONNECT_STATIC_NAMESPACE] = (0, _lodash.uniq)(mergedNamespace); // @ts-ignore PolymorphicComponent property
WrappedComponent.selector = `.${(0, _getStyledClassNameFromKey.getStyledClassNameFromKey)(namespace)}`; // @ts-ignore
return WrappedComponent;
}
/**
* Attempts to retrieve the connected namespace from a component.
*
* @param {import('react').ReactChild | undefined | {}} Component The component to retrieve a namespace from.
* @return {Array<string>} The connected namespaces.
*/
function getConnectNamespace(Component) {
if (!Component) return [];
let namespaces = []; // @ts-ignore internal property
if (Component[_constants.CONNECT_STATIC_NAMESPACE]) {
// @ts-ignore internal property
namespaces = Component[_constants.CONNECT_STATIC_NAMESPACE];
} // @ts-ignore
if (Component.type && Component.type[_constants.CONNECT_STATIC_NAMESPACE]) {
// @ts-ignore
namespaces = Component.type[_constants.CONNECT_STATIC_NAMESPACE];
}
return namespaces;
}
/**
* Checks to see if a component is connected within the Context system.
*
* @param {import('react').ReactNode} Component The component to retrieve a namespace from.
* @param {Array<string>|string} match The namespace to check.
* @return {boolean} The result.
*/
function hasConnectNamespace(Component, match) {
if (!Component) return false;
if (typeof match === 'string') {
return getConnectNamespace(Component).includes(match);
}
if (Array.isArray(match)) {
return match.some(result => getConnectNamespace(Component).includes(result));
}
return false;
}
//# sourceMappingURL=context-connect.js.map