@wordpress/components
Version:
UI components for WordPress.
73 lines (70 loc) • 2.38 kB
JavaScript
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { useObservableValue } from '@wordpress/compose';
import { useContext, useLayoutEffect, useRef, Children, cloneElement, isEmptyElement } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './context';
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
/**
* Whether the argument is a function.
*
* @param maybeFunc The argument to check.
* @return True if the argument is a function, false otherwise.
*/
function isFunction(maybeFunc) {
return typeof maybeFunc === 'function';
}
function addKeysToChildren(children) {
return Children.map(children, (child, childIndex) => {
if (!child || typeof child === 'string') {
return child;
}
let childKey = childIndex;
if (typeof child === 'object' && 'key' in child && child?.key) {
childKey = child.key;
}
return cloneElement(child, {
key: childKey
});
});
}
function Slot(props) {
var _useObservableValue;
const registry = useContext(SlotFillContext);
const instanceRef = useRef({});
const {
name,
children,
fillProps = {}
} = props;
useLayoutEffect(() => {
const instance = instanceRef.current;
registry.registerSlot(name, instance);
return () => registry.unregisterSlot(name, instance);
}, [registry, name]);
let fills = (_useObservableValue = useObservableValue(registry.fills, name)) !== null && _useObservableValue !== void 0 ? _useObservableValue : [];
const currentSlot = useObservableValue(registry.slots, name);
// Fills should only be rendered in the currently registered instance of the slot.
if (currentSlot !== instanceRef.current) {
fills = [];
}
const renderedFills = fills.map(fill => {
const fillChildren = isFunction(fill.children) ? fill.children(fillProps) : fill.children;
return addKeysToChildren(fillChildren);
}).filter(
// In some cases fills are rendered only when some conditions apply.
// This ensures that we only use non-empty fills when rendering, i.e.,
// it allows us to render wrappers only when the fills are actually present.
element => !isEmptyElement(element));
return /*#__PURE__*/_jsx(_Fragment, {
children: isFunction(children) ? children(renderedFills) : renderedFills
});
}
export default Slot;
//# sourceMappingURL=slot.js.map