@wordpress/block-editor
Version:
192 lines (184 loc) • 7.23 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _i18n = require("@wordpress/i18n");
var _element = require("@wordpress/element");
var _components = require("@wordpress/components");
var _blocks = require("@wordpress/blocks");
var _data = require("@wordpress/data");
var _components2 = require("../components");
var _store = require("../store");
var _jsxRuntime = require("react/jsx-runtime");
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const EMPTY_OBJECT = {};
function BlockHooksControlPure({
name,
clientId,
metadata: {
ignoredHookedBlocks = []
} = {}
}) {
const blockTypes = (0, _data.useSelect)(select => select(_blocks.store).getBlockTypes(), []);
// A hooked block added via a filter will not be exposed through a block
// type's `blockHooks` property; however, if the containing layout has been
// modified, it will be present in the anchor block's `ignoredHookedBlocks`
// metadata.
const hookedBlocksForCurrentBlock = (0, _element.useMemo)(() => blockTypes?.filter(({
name: blockName,
blockHooks
}) => blockHooks && name in blockHooks || ignoredHookedBlocks.includes(blockName)), [blockTypes, name, ignoredHookedBlocks]);
const hookedBlockClientIds = (0, _data.useSelect)(select => {
const {
getBlocks,
getBlockRootClientId,
getGlobalBlockCount
} = select(_store.store);
const rootClientId = getBlockRootClientId(clientId);
const _hookedBlockClientIds = hookedBlocksForCurrentBlock.reduce((clientIds, block) => {
// If the block doesn't exist anywhere in the block tree,
// we know that we have to set the toggle to disabled.
if (getGlobalBlockCount(block.name) === 0) {
return clientIds;
}
const relativePosition = block?.blockHooks?.[name];
let candidates;
switch (relativePosition) {
case 'before':
case 'after':
// Any of the current block's siblings (with the right block type) qualifies
// as a hooked block (inserted `before` or `after` the current one), as the block
// might've been automatically inserted and then moved around a bit by the user.
candidates = getBlocks(rootClientId);
break;
case 'first_child':
case 'last_child':
// Any of the current block's child blocks (with the right block type) qualifies
// as a hooked first or last child block, as the block might've been automatically
// inserted and then moved around a bit by the user.
candidates = getBlocks(clientId);
break;
case undefined:
// If we haven't found a blockHooks field with a relative position for the hooked
// block, it means that it was added by a filter. In this case, we look for the block
// both among the current block's siblings and its children.
candidates = [...getBlocks(rootClientId), ...getBlocks(clientId)];
break;
}
const hookedBlock = candidates?.find(candidate => candidate.name === block.name);
// If the block exists in the designated location, we consider it hooked
// and show the toggle as enabled.
if (hookedBlock) {
return {
...clientIds,
[block.name]: hookedBlock.clientId
};
}
// If no hooked block was found in any of its designated locations,
// we set the toggle to disabled.
return clientIds;
}, {});
if (Object.values(_hookedBlockClientIds).length > 0) {
return _hookedBlockClientIds;
}
return EMPTY_OBJECT;
}, [hookedBlocksForCurrentBlock, name, clientId]);
const {
getBlockIndex,
getBlockCount,
getBlockRootClientId
} = (0, _data.useSelect)(_store.store);
const {
insertBlock,
removeBlock
} = (0, _data.useDispatch)(_store.store);
if (!hookedBlocksForCurrentBlock.length) {
return null;
}
// Group by block namespace (i.e. prefix before the slash).
const groupedHookedBlocks = hookedBlocksForCurrentBlock.reduce((groups, block) => {
const [namespace] = block.name.split('/');
if (!groups[namespace]) {
groups[namespace] = [];
}
groups[namespace].push(block);
return groups;
}, {});
const insertBlockIntoDesignatedLocation = (block, relativePosition) => {
const blockIndex = getBlockIndex(clientId);
const innerBlocksLength = getBlockCount(clientId);
const rootClientId = getBlockRootClientId(clientId);
switch (relativePosition) {
case 'before':
case 'after':
insertBlock(block, relativePosition === 'after' ? blockIndex + 1 : blockIndex, rootClientId,
// Insert as a child of the current block's parent
false);
break;
case 'first_child':
case 'last_child':
insertBlock(block,
// TODO: It'd be great if insertBlock() would accept negative indices for insertion.
relativePosition === 'first_child' ? 0 : innerBlocksLength, clientId,
// Insert as a child of the current block.
false);
break;
case undefined:
// If we do not know the relative position, it is because the block was
// added via a filter. In this case, we default to inserting it after the
// current block.
insertBlock(block, blockIndex + 1, rootClientId,
// Insert as a child of the current block's parent
false);
break;
}
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components2.InspectorControls, {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.PanelBody, {
className: "block-editor-hooks__block-hooks",
title: (0, _i18n.__)('Plugins'),
initialOpen: true,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
className: "block-editor-hooks__block-hooks-helptext",
children: (0, _i18n.__)('Manage the inclusion of blocks added automatically by plugins.')
}), Object.keys(groupedHookedBlocks).map(vendor => {
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_element.Fragment, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h3", {
children: vendor
}), groupedHookedBlocks[vendor].map(block => {
const checked = block.name in hookedBlockClientIds;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToggleControl, {
__nextHasNoMarginBottom: true,
checked: checked,
label: block.title,
onChange: () => {
if (!checked) {
// Create and insert block.
const relativePosition = block.blockHooks[name];
insertBlockIntoDesignatedLocation((0, _blocks.createBlock)(block.name), relativePosition);
return;
}
// Remove block.
removeBlock(hookedBlockClientIds[block.name], false);
}
}, block.title);
})]
}, vendor);
})]
})
});
}
var _default = exports.default = {
edit: BlockHooksControlPure,
attributeKeys: ['metadata'],
hasSupport() {
return true;
}
};
//# sourceMappingURL=block-hooks.js.map
;