UNPKG

@wordpress/block-editor

Version:
266 lines (256 loc) 9.97 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; exports.useInnerBlocksProps = useInnerBlocksProps; var _clsx = _interopRequireDefault(require("clsx")); var _compose = require("@wordpress/compose"); var _element = require("@wordpress/element"); var _data = require("@wordpress/data"); var _blocks = require("@wordpress/blocks"); var _buttonBlockAppender = _interopRequireDefault(require("./button-block-appender")); var _defaultBlockAppender = _interopRequireDefault(require("./default-block-appender")); var _useNestedSettingsUpdate = _interopRequireDefault(require("./use-nested-settings-update")); var _useInnerBlockTemplateSync = _interopRequireDefault(require("./use-inner-block-template-sync")); var _useBlockContext = _interopRequireDefault(require("./use-block-context")); var _blockList = require("../block-list"); var _blockContext = require("../block-context"); var _context = require("../block-edit/context"); var _useBlockSync = _interopRequireDefault(require("../provider/use-block-sync")); var _store = require("../../store"); var _useBlockDropZone = _interopRequireDefault(require("../use-block-drop-zone")); var _lockUnlock = require("../../lock-unlock"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const EMPTY_OBJECT = {}; function BlockContext({ children, clientId }) { const context = (0, _useBlockContext.default)(clientId); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockContext.BlockContextProvider, { value: context, children: children }); } const BlockListItemsMemo = (0, _element.memo)(_blockList.BlockListItems); /** * InnerBlocks is a component which allows a single block to have multiple blocks * as children. The UncontrolledInnerBlocks component is used whenever the inner * blocks are not controlled by another entity. In other words, it is normally * used for inner blocks in the post editor * * @param {Object} props The component props. */ function UncontrolledInnerBlocks(props) { const { clientId, allowedBlocks, prioritizedInserterBlocks, defaultBlock, directInsert, __experimentalDefaultBlock, __experimentalDirectInsert, template, templateLock, wrapperRef, templateInsertUpdatesSelection, __experimentalCaptureToolbars: captureToolbars, __experimentalAppenderTagName, renderAppender, orientation, placeholder, layout, name, blockType, parentLock, defaultLayout } = props; (0, _useNestedSettingsUpdate.default)(clientId, parentLock, allowedBlocks, prioritizedInserterBlocks, defaultBlock, directInsert, __experimentalDefaultBlock, __experimentalDirectInsert, templateLock, captureToolbars, orientation, layout); (0, _useInnerBlockTemplateSync.default)(clientId, template, templateLock, templateInsertUpdatesSelection); const defaultLayoutBlockSupport = (0, _blocks.getBlockSupport)(name, 'layout') || (0, _blocks.getBlockSupport)(name, '__experimentalLayout') || EMPTY_OBJECT; const { allowSizingOnChildren = false } = defaultLayoutBlockSupport; const usedLayout = layout || defaultLayoutBlockSupport; const memoedLayout = (0, _element.useMemo)(() => ({ // Default layout will know about any content/wide size defined by the theme. ...defaultLayout, ...usedLayout, ...(allowSizingOnChildren && { allowSizingOnChildren: true }) }), [defaultLayout, usedLayout, allowSizingOnChildren]); // For controlled inner blocks, we don't want a change in blocks to // re-render the blocks list. const items = /*#__PURE__*/(0, _jsxRuntime.jsx)(BlockListItemsMemo, { rootClientId: clientId, renderAppender: renderAppender, __experimentalAppenderTagName: __experimentalAppenderTagName, layout: memoedLayout, wrapperRef: wrapperRef, placeholder: placeholder }); if (!blockType?.providesContext || Object.keys(blockType.providesContext).length === 0) { return items; } return /*#__PURE__*/(0, _jsxRuntime.jsx)(BlockContext, { clientId: clientId, children: items }); } /** * The controlled inner blocks component wraps the uncontrolled inner blocks * component with the blockSync hook. This keeps the innerBlocks of the block in * the block-editor store in sync with the blocks of the controlling entity. An * example of an inner block controller is a template part block, which provides * its own blocks from the template part entity data source. * * @param {Object} props The component props. */ function ControlledInnerBlocks(props) { (0, _useBlockSync.default)(props); return /*#__PURE__*/(0, _jsxRuntime.jsx)(UncontrolledInnerBlocks, { ...props }); } const ForwardedInnerBlocks = (0, _element.forwardRef)((props, ref) => { const innerBlocksProps = useInnerBlocksProps({ ref }, props); return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "block-editor-inner-blocks", children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { ...innerBlocksProps }) }); }); /** * This hook is used to lightly mark an element as an inner blocks wrapper * element. Call this hook and pass the returned props to the element to mark as * an inner blocks wrapper, automatically rendering inner blocks as children. If * you define a ref for the element, it is important to pass the ref to this * hook, which the hook in turn will pass to the component through the props it * returns. Optionally, you can also pass any other props through this hook, and * they will be merged and returned. * * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md * * @param {Object} props Optional. Props to pass to the element. Must contain * the ref if one is defined. * @param {Object} options Optional. Inner blocks options. */ function useInnerBlocksProps(props = {}, options = {}) { const { __unstableDisableLayoutClassNames, __unstableDisableDropZone, dropZoneElement } = options; const { clientId, layout = null, __unstableLayoutClassNames: layoutClassNames = '' } = (0, _context.useBlockEditContext)(); const selected = (0, _data.useSelect)(select => { const { getBlockName, isZoomOut, getTemplateLock, getBlockRootClientId, getBlockEditingMode, getBlockSettings, getSectionRootClientId } = (0, _lockUnlock.unlock)(select(_store.store)); if (!clientId) { const sectionRootClientId = getSectionRootClientId(); // Disable the root drop zone when zoomed out and the section root client id // is not the root block list (represented by an empty string). // This avoids drag handling bugs caused by having two block lists acting as // drop zones - the actual 'root' block list and the section root. return { isDropZoneDisabled: isZoomOut() && sectionRootClientId !== '' }; } const { hasBlockSupport, getBlockType } = select(_blocks.store); const blockName = getBlockName(clientId); const blockEditingMode = getBlockEditingMode(clientId); const parentClientId = getBlockRootClientId(clientId); const [defaultLayout] = getBlockSettings(clientId, 'layout'); let _isDropZoneDisabled = blockEditingMode === 'disabled'; if (isZoomOut()) { // In zoom out mode, we want to disable the drop zone for the sections. // The inner blocks belonging to the section drop zone is // already disabled by the blocks themselves being disabled. const sectionRootClientId = getSectionRootClientId(); _isDropZoneDisabled = clientId !== sectionRootClientId; } return { __experimentalCaptureToolbars: hasBlockSupport(blockName, '__experimentalExposeControlsToChildren', false), name: blockName, blockType: getBlockType(blockName), parentLock: getTemplateLock(parentClientId), parentClientId, isDropZoneDisabled: _isDropZoneDisabled, defaultLayout }; }, [clientId]); const { __experimentalCaptureToolbars, name, blockType, parentLock, parentClientId, isDropZoneDisabled, defaultLayout } = selected; const blockDropZoneRef = (0, _useBlockDropZone.default)({ dropZoneElement, rootClientId: clientId, parentClientId }); const ref = (0, _compose.useMergeRefs)([props.ref, __unstableDisableDropZone || isDropZoneDisabled || layout?.isManualPlacement && window.__experimentalEnableGridInteractivity ? null : blockDropZoneRef]); const innerBlocksProps = { __experimentalCaptureToolbars, layout, name, blockType, parentLock, defaultLayout, ...options }; const InnerBlocks = innerBlocksProps.value && innerBlocksProps.onChange ? ControlledInnerBlocks : UncontrolledInnerBlocks; return { ...props, ref, className: (0, _clsx.default)(props.className, 'block-editor-block-list__layout', __unstableDisableLayoutClassNames ? '' : layoutClassNames), children: clientId ? /*#__PURE__*/(0, _jsxRuntime.jsx)(InnerBlocks, { ...innerBlocksProps, clientId: clientId }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockList.BlockListItems, { ...options }) }; } useInnerBlocksProps.save = _blocks.__unstableGetInnerBlocksProps; // Expose default appender placeholders as components. ForwardedInnerBlocks.DefaultBlockAppender = _defaultBlockAppender.default; ForwardedInnerBlocks.ButtonBlockAppender = _buttonBlockAppender.default; ForwardedInnerBlocks.Content = () => useInnerBlocksProps.save().children; /** * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md */ var _default = exports.default = ForwardedInnerBlocks; //# sourceMappingURL=index.js.map