@wordpress/block-editor
Version:
120 lines (101 loc) • 3.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__unstableUseBlockElement = useBlockElement;
exports.__unstableUseBlockRef = useBlockRef;
exports.useBlockRefProvider = useBlockRefProvider;
var _element = require("@wordpress/element");
var _compose = require("@wordpress/compose");
var _blockRefsProvider = require("../../provider/block-refs-provider");
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/** @typedef {import('@wordpress/element').RefCallback} RefCallback */
/** @typedef {import('@wordpress/element').RefObject} RefObject */
/**
* Provides a ref to the BlockRefs context.
*
* @param {string} clientId The client ID of the element ref.
*
* @return {RefCallback} Ref callback.
*/
function useBlockRefProvider(clientId) {
const {
refs,
callbacks
} = (0, _element.useContext)(_blockRefsProvider.BlockRefs);
const ref = (0, _element.useRef)();
(0, _element.useLayoutEffect)(() => {
refs.set(ref, clientId);
return () => {
refs.delete(ref);
};
}, [clientId]);
return (0, _compose.useRefEffect)(element => {
// Update the ref in the provider.
ref.current = element; // Call any update functions.
callbacks.forEach((id, setElement) => {
if (clientId === id) {
setElement(element);
}
});
}, [clientId]);
}
/**
* Gets a ref pointing to the current block element. Continues to return a
* stable ref even if the block client ID changes.
*
* @param {string} clientId The client ID to get a ref for.
*
* @return {RefObject} A ref containing the element.
*/
function useBlockRef(clientId) {
const {
refs
} = (0, _element.useContext)(_blockRefsProvider.BlockRefs);
const freshClientId = (0, _element.useRef)();
freshClientId.current = clientId; // Always return an object, even if no ref exists for a given client ID, so
// that `current` works at a later point.
return (0, _element.useMemo)(() => ({
get current() {
let element = null; // Multiple refs may be created for a single block. Find the
// first that has an element set.
for (const [ref, id] of refs.entries()) {
if (id === freshClientId.current && ref.current) {
element = ref.current;
}
}
return element;
}
}), []);
}
/**
* Return the element for a given client ID. Updates whenever the element
* changes, becomes available, or disappears.
*
* @param {string} clientId The client ID to an element for.
*
* @return {Element|null} The block's wrapper element.
*/
function useBlockElement(clientId) {
const {
callbacks
} = (0, _element.useContext)(_blockRefsProvider.BlockRefs);
const ref = useBlockRef(clientId);
const [element, setElement] = (0, _element.useState)(null);
(0, _element.useLayoutEffect)(() => {
if (!clientId) {
return;
}
callbacks.set(setElement, clientId);
return () => {
callbacks.delete(setElement);
};
}, [clientId]);
return ref.current || element;
}
//# sourceMappingURL=use-block-refs.js.map