@wordpress/block-editor
Version:
97 lines (90 loc) • 4.76 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = useInnerBlockTemplateSync;
var _es = _interopRequireDefault(require("fast-deep-equal/es6"));
var _element = require("@wordpress/element");
var _data = require("@wordpress/data");
var _blocks = require("@wordpress/blocks");
var _store = require("../../store");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* This hook makes sure that a block's inner blocks stay in sync with the given
* block "template". The template is a block hierarchy to which inner blocks must
* conform. If the blocks get "out of sync" with the template and the template
* is meant to be locked (e.g. templateLock = "all" or templateLock = "contentOnly"),
* then we replace the inner blocks with the correct value after synchronizing it with the template.
*
* @param {string} clientId The block client ID.
* @param {Object} template The template to match.
* @param {string} templateLock The template lock state for the inner blocks. For
* example, if the template lock is set to "all",
* then the inner blocks will stay in sync with the
* template. If not defined or set to false, then
* the inner blocks will not be synchronized with
* the given template.
* @param {boolean} templateInsertUpdatesSelection Whether or not to update the
* block-editor selection state when inner blocks
* are replaced after template synchronization.
*/
function useInnerBlockTemplateSync(clientId, template, templateLock, templateInsertUpdatesSelection) {
// Instead of adding a useSelect mapping here, please add to the useSelect
// mapping in InnerBlocks! Every subscription impacts performance.
const registry = (0, _data.useRegistry)();
// Maintain a reference to the previous value so we can do a deep equality check.
const existingTemplateRef = (0, _element.useRef)(null);
(0, _element.useLayoutEffect)(() => {
let isCancelled = false;
const {
getBlocks,
getSelectedBlocksInitialCaretPosition,
isBlockSelected
} = registry.select(_store.store);
const {
replaceInnerBlocks,
__unstableMarkNextChangeAsNotPersistent
} = registry.dispatch(_store.store);
// There's an implicit dependency between useInnerBlockTemplateSync and useNestedSettingsUpdate
// The former needs to happen after the latter and since the latter is using microtasks to batch updates (performance optimization),
// we need to schedule this one in a microtask as well.
// Example: If you remove queueMicrotask here, ctrl + click to insert quote block won't close the inserter.
window.queueMicrotask(() => {
if (isCancelled) {
return;
}
// Only synchronize innerBlocks with template if innerBlocks are empty
// or a locking "all" or "contentOnly" exists directly on the block.
const currentInnerBlocks = getBlocks(clientId);
const shouldApplyTemplate = currentInnerBlocks.length === 0 || templateLock === 'all' || templateLock === 'contentOnly';
const hasTemplateChanged = !(0, _es.default)(template, existingTemplateRef.current);
if (!shouldApplyTemplate || !hasTemplateChanged) {
return;
}
existingTemplateRef.current = template;
const nextBlocks = (0, _blocks.synchronizeBlocksWithTemplate)(currentInnerBlocks, template);
if (!(0, _es.default)(nextBlocks, currentInnerBlocks)) {
__unstableMarkNextChangeAsNotPersistent();
replaceInnerBlocks(clientId, nextBlocks, currentInnerBlocks.length === 0 && templateInsertUpdatesSelection && nextBlocks.length !== 0 && isBlockSelected(clientId),
// This ensures the "initialPosition" doesn't change when applying the template
// If we're supposed to focus the block, we'll focus the first inner block
// otherwise, we won't apply any auto-focus.
// This ensures for instance that the focus stays in the inserter when inserting the "buttons" block.
getSelectedBlocksInitialCaretPosition());
}
});
return () => {
isCancelled = true;
};
}, [template, templateLock, clientId, registry, templateInsertUpdatesSelection]);
}
//# sourceMappingURL=use-inner-block-template-sync.js.map
;