UNPKG

@wordpress/block-editor

Version:
325 lines (274 loc) 9.46 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.BlockListBlockContext = void 0; var _element = require("@wordpress/element"); var _classnames = _interopRequireDefault(require("classnames")); var _lodash = require("lodash"); var _blocks = require("@wordpress/blocks"); var _components = require("@wordpress/components"); var _data = require("@wordpress/data"); var _compose = require("@wordpress/compose"); var _blockEdit = _interopRequireDefault(require("../block-edit")); var _blockInvalidWarning = _interopRequireDefault(require("./block-invalid-warning")); var _blockCrashWarning = _interopRequireDefault(require("./block-crash-warning")); var _blockCrashBoundary = _interopRequireDefault(require("./block-crash-boundary")); var _blockHtml = _interopRequireDefault(require("./block-html")); var _useBlockProps = require("./use-block-props"); var _store = require("../../store"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const BlockListBlockContext = (0, _element.createContext)(); /** * Merges wrapper props with special handling for classNames and styles. * * @param {Object} propsA * @param {Object} propsB * * @return {Object} Merged props. */ exports.BlockListBlockContext = BlockListBlockContext; function mergeWrapperProps(propsA, propsB) { const newProps = { ...propsA, ...propsB }; if (propsA && propsB && propsA.className && propsB.className) { newProps.className = (0, _classnames.default)(propsA.className, propsB.className); } if (propsA && propsB && propsA.style && propsB.style) { newProps.style = { ...propsA.style, ...propsB.style }; } return newProps; } function Block({ children, isHtml, ...props }) { return (0, _element.createElement)("div", (0, _useBlockProps.useBlockProps)(props, { __unstableIsHtml: isHtml }), children); } function BlockListBlock({ mode, isLocked, clientId, isSelected, isSelectionEnabled, className, name, isValid, attributes, wrapperProps, setAttributes, onReplace, onInsertBlocksAfter, onMerge, toggleSelection, index }) { const { removeBlock } = (0, _data.useDispatch)(_store.store); const onRemove = (0, _element.useCallback)(() => removeBlock(clientId), [clientId]); // We wrap the BlockEdit component in a div that hides it when editing in // HTML mode. This allows us to render all of the ancillary pieces // (InspectorControls, etc.) which are inside `BlockEdit` but not // `BlockHTML`, even in HTML mode. let blockEdit = (0, _element.createElement)(_blockEdit.default, { name: name, isSelected: isSelected, attributes: attributes, setAttributes: setAttributes, insertBlocksAfter: isLocked ? undefined : onInsertBlocksAfter, onReplace: isLocked ? undefined : onReplace, onRemove: isLocked ? undefined : onRemove, mergeBlocks: isLocked ? undefined : onMerge, clientId: clientId, isSelectionEnabled: isSelectionEnabled, toggleSelection: toggleSelection }); const blockType = (0, _blocks.getBlockType)(name); const lightBlockWrapper = blockType.apiVersion > 1 || (0, _blocks.hasBlockSupport)(blockType, 'lightBlockWrapper', false); // Determine whether the block has props to apply to the wrapper. if (blockType.getEditWrapperProps) { wrapperProps = mergeWrapperProps(wrapperProps, blockType.getEditWrapperProps(attributes)); } const isAligned = wrapperProps && !!wrapperProps['data-align']; // For aligned blocks, provide a wrapper element so the block can be // positioned relative to the block column. if (isAligned) { blockEdit = (0, _element.createElement)("div", { className: "wp-block", "data-align": wrapperProps['data-align'] }, blockEdit); } let block; if (!isValid) { block = (0, _element.createElement)(Block, { className: "has-warning" }, (0, _element.createElement)(_blockInvalidWarning.default, { clientId: clientId }), (0, _element.createElement)("div", null, (0, _blocks.getSaveElement)(blockType, attributes))); } else if (mode === 'html') { // Render blockEdit so the inspector controls don't disappear. // See #8969. block = (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)("div", { style: { display: 'none' } }, blockEdit), (0, _element.createElement)(Block, { isHtml: true }, (0, _element.createElement)(_blockHtml.default, { clientId: clientId }))); } else if (lightBlockWrapper) { block = blockEdit; } else { block = (0, _element.createElement)(Block, wrapperProps, blockEdit); } const value = { clientId, isSelected, index, // The wp-block className is important for editor styles. className: (0, _classnames.default)(className, { 'wp-block': !isAligned }), wrapperProps: (0, _lodash.omit)(wrapperProps, ['data-align']) }; const memoizedValue = (0, _element.useMemo)(() => value, Object.values(value)); return (0, _element.createElement)(BlockListBlockContext.Provider, { value: memoizedValue }, (0, _element.createElement)(_blockCrashBoundary.default, { fallback: (0, _element.createElement)(Block, { className: "has-warning" }, (0, _element.createElement)(_blockCrashWarning.default, null)) }, block)); } const applyWithSelect = (0, _data.withSelect)((select, { clientId, rootClientId }) => { const { isBlockSelected, getBlockMode, isSelectionEnabled, getTemplateLock, __unstableGetBlockWithoutInnerBlocks } = select(_store.store); const block = __unstableGetBlockWithoutInnerBlocks(clientId); const isSelected = isBlockSelected(clientId); const templateLock = getTemplateLock(rootClientId); // The fallback to `{}` is a temporary fix. // This function should never be called when a block is not present in // the state. It happens now because the order in withSelect rendering // is not correct. const { name, attributes, isValid } = block || {}; // Do not add new properties here, use `useSelect` instead to avoid // leaking new props to the public API (editor.BlockListBlock filter). return { mode: getBlockMode(clientId), isSelectionEnabled: isSelectionEnabled(), isLocked: !!templateLock, // Users of the editor.BlockListBlock filter used to be able to // access the block prop. // Ideally these blocks would rely on the clientId prop only. // This is kept for backward compatibility reasons. block, name, attributes, isValid, isSelected }; }); const applyWithDispatch = (0, _data.withDispatch)((dispatch, ownProps, { select }) => { const { updateBlockAttributes, insertBlocks, mergeBlocks, replaceBlocks, toggleSelection, __unstableMarkLastChangeAsPersistent } = dispatch(_store.store); // Do not add new properties here, use `useDispatch` instead to avoid // leaking new props to the public API (editor.BlockListBlock filter). return { setAttributes(newAttributes) { const { getMultiSelectedBlockClientIds } = select(_store.store); const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(); const { clientId } = ownProps; const clientIds = multiSelectedBlockClientIds.length ? multiSelectedBlockClientIds : [clientId]; updateBlockAttributes(clientIds, newAttributes); }, onInsertBlocks(blocks, index) { const { rootClientId } = ownProps; insertBlocks(blocks, index, rootClientId); }, onInsertBlocksAfter(blocks) { const { clientId, rootClientId } = ownProps; const { getBlockIndex } = select(_store.store); const index = getBlockIndex(clientId, rootClientId); insertBlocks(blocks, index + 1, rootClientId); }, onMerge(forward) { const { clientId } = ownProps; const { getPreviousBlockClientId, getNextBlockClientId } = select(_store.store); if (forward) { const nextBlockClientId = getNextBlockClientId(clientId); if (nextBlockClientId) { mergeBlocks(clientId, nextBlockClientId); } } else { const previousBlockClientId = getPreviousBlockClientId(clientId); if (previousBlockClientId) { mergeBlocks(previousBlockClientId, clientId); } } }, onReplace(blocks, indexToSelect, initialPosition) { if (blocks.length && !(0, _blocks.isUnmodifiedDefaultBlock)(blocks[blocks.length - 1])) { __unstableMarkLastChangeAsPersistent(); } replaceBlocks([ownProps.clientId], blocks, indexToSelect, initialPosition); }, toggleSelection(selectionEnabled) { toggleSelection(selectionEnabled); } }; }); var _default = (0, _compose.compose)(_compose.pure, applyWithSelect, applyWithDispatch, // block is sometimes not mounted at the right time, causing it be undefined // see issue for more info // https://github.com/WordPress/gutenberg/issues/17013 (0, _compose.ifCondition)(({ block }) => !!block), (0, _components.withFilters)('editor.BlockListBlock'))(BlockListBlock); exports.default = _default; //# sourceMappingURL=block.js.map