@wordpress/block-editor
Version:
266 lines (256 loc) • 9.97 kB
JavaScript
"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