UNPKG

@wordpress/block-editor

Version:
192 lines (184 loc) 7.23 kB
"use strict"; 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