: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (dropZoneElement && parentBlockOrientation === 'horizontal') {
const rect = dropZoneElement.getBoundingClientRect();
const [distance, edge] = getDistanceToNearestEdge(position, rect, ['left', 'right']);
// If dragging over the left or right of the drop zone, insert the block
// before or after the parent block. This only applies to blocks that use
// a drop zone element, typically container blocks such as Group.
if (rect.width > MINIMUM_WIDTH_FOR_THRESHOLD && distance < THRESHOLD_DISTANCE) {
if (isRightToLeft && edge === 'right' || !isRightToLeft && edge === 'left') {
return [rootBlockIndex, 'before'];
if (isRightToLeft && edge === 'left' || !isRightToLeft && edge === 'right') {
return [rootBlockIndex + 1, 'after'];
isUnmodifiedDefaultBlock,
const rect = getBoundingClientRect();
let [distance, edge] = getDistanceToNearestEdge(position, rect, allowedEdges);
// If the the point is close to a side, prioritize that side.
const [sideDistance, sideEdge] = getDistanceToNearestEdge(position, rect, ['left', 'right']);
const isPointInsideRect = isPointContainedByRect(position, rect);
// Prioritize the element if the point is inside of an unmodified default block.
if (isUnmodifiedDefaultBlock && isPointInsideRect) {
} else if (orientation === 'vertical' && blockOrientation !== 'horizontal' && (isPointInsideRect && sideDistance < THRESHOLD_DISTANCE || !isPointInsideRect && isPointWithinTopAndBottomBoundariesOfRect(position, rect))) {
* This condition should only apply when the layout is vertical (otherwise there's
* no need to create a Row) and dropzones should only activate when the block is
* either within and close to the sides of the target block or on its outer sides.
targetBlockIndex = blockIndex;
if (distance < minDistance) {
// Where the dropped block will be inserted on the nearest block.
insertPosition = edge === 'bottom' || !isRightToLeft && edge === 'right' || isRightToLeft && edge === 'left' ? 'after' : 'before';
// Update the currently known best candidate.
nearestIndex = blockIndex;
const adjacentIndex = nearestIndex + (insertPosition === 'after' ? 1 : -1);
const isNearestBlockUnmodifiedDefaultBlock = !!blocksData[nearestIndex]?.isUnmodifiedDefaultBlock;
const isAdjacentBlockUnmodifiedDefaultBlock = !!blocksData[adjacentIndex]?.isUnmodifiedDefaultBlock;
// If the target index is set then group with the block at that index.
if (targetBlockIndex !== null) {
return [targetBlockIndex, 'group', nearestSide];
// If both blocks are not unmodified default blocks then just insert between them.
if (!isNearestBlockUnmodifiedDefaultBlock && !isAdjacentBlockUnmodifiedDefaultBlock) {
// If the user is dropping to the trailing edge of the block
// add 1 to the index to represent dragging after.
const insertionIndex = insertPosition === 'after' ? nearestIndex + 1 : nearestIndex;
return [insertionIndex, 'insert'];
// Otherwise, replace the nearest unmodified default block.
return [isNearestBlockUnmodifiedDefaultBlock ? nearestIndex : adjacentIndex, 'replace'];
* Check if the dragged blocks can be dropped on the target.
* @param {Function} getBlockType
* @param {Object[]} allowedBlocks
* @param {string[]} draggedBlockNames
* @param {string} targetBlockName
* @return {boolean} Whether the dragged blocks can be dropped on the target.
function isDropTargetValid(getBlockType, allowedBlocks, draggedBlockNames, targetBlockName) {
// At root level allowedBlocks is undefined and all blocks are allowed.
// Otherwise, check if all dragged blocks are allowed.
let areBlocksAllowed = true;
const allowedBlockNames = allowedBlocks?.map(({
areBlocksAllowed = draggedBlockNames.every(name => allowedBlockNames?.includes(name));
// Work out if dragged blocks have an allowed parent and if so
// check target block matches the allowed parent.
const draggedBlockTypes = draggedBlockNames.map(name => getBlockType(name));
const targetMatchesDraggedBlockParents = draggedBlockTypes.every(block => {
const [allowedParentName] = block?.parent || [];
if (!allowedParentName) {
return allowedParentName === targetBlockName;
return areBlocksAllowed && targetMatchesDraggedBlockParents;
* @typedef {Object} WPBlockDropZoneConfig
* @property {?HTMLElement} dropZoneElement Optional element to be used as the drop zone.
* @property {string} rootClientId The root client id for the block list.
* A React hook that can be used to make a block list handle drag and drop.
* @param {WPBlockDropZoneConfig} dropZoneConfig configuration data for the drop zone.
function useBlockDropZone({
// An undefined value represents a top-level block. Default to an empty
// string for this so that `targetRootClientId` can be easily compared to
// values returned by the `getRootBlockClientId` selector, which also uses
// an empty string to represent top-level blocks.
rootClientId: targetRootClientId = '',
parentClientId: parentBlockClientId = '',
const registry = (0,external_wp_data_namespaceObject.useRegistry)();
const [dropTarget, setDropTarget] = (0,external_wp_element_namespaceObject.useState)({
} = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blocks_namespaceObject.store);
getDraggedBlockClientIds,
} = unlock((0,external_wp_data_namespaceObject.useSelect)(store));
} = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
const onBlockDrop = useOnBlockDrop(dropTarget.operation === 'before' || dropTarget.operation === 'after' ? parentBlockClientId : targetRootClientId, dropTarget.index, {
operation: dropTarget.operation,
nearestSide: dropTarget.nearestSide
const throttled = (0,external_wp_compose_namespaceObject.useThrottle)((0,external_wp_element_namespaceObject.useCallback)((event, ownerDocument) => {
// When dragging from the desktop, no drag start event is fired.
// So, ensure that the drag state is set when the user drags over a drop zone.
const allowedBlocks = getAllowedBlocks(targetRootClientId);
const targetBlockName = getBlockNamesByClientId([targetRootClientId])[0];
const draggedBlockNames = getBlockNamesByClientId(getDraggedBlockClientIds());
const isBlockDroppingAllowed = isDropTargetValid(getBlockType, allowedBlocks, draggedBlockNames, targetBlockName);
if (!isBlockDroppingAllowed) {
const blocks = getBlocks(targetRootClientId);
// The block list is empty, don't show the insertion point but still allow dropping.
if (blocks.length === 0) {
showInsertionPoint(targetRootClientId, 0, {
const blocksData = blocks.map(block => {
const clientId = block.clientId;
isUnmodifiedDefaultBlock: (0,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(block),
getBoundingClientRect: () => ownerDocument.getElementById(`block-${clientId}`).getBoundingClientRect(),
blockIndex: getBlockIndex(clientId),
blockOrientation: getBlockListSettings(clientId)?.orientation
const [targetIndex, operation, nearestSide] = getDropTargetPosition(blocksData, {
}, getBlockListSettings(targetRootClientId)?.orientation, {
parentBlockOrientation: parentBlockClientId ? getBlockListSettings(parentBlockClientId)?.orientation : undefined,
rootBlockIndex: getBlockIndex(targetRootClientId)
const insertionPointClientId = ['before', 'after'].includes(operation) ? parentBlockClientId : targetRootClientId;
showInsertionPoint(insertionPointClientId, targetIndex, {
}, [getAllowedBlocks, targetRootClientId, getBlockNamesByClientId, getDraggedBlockClientIds, getBlockType, getBlocks, getBlockListSettings, dropZoneElement, parentBlockClientId, getBlockIndex, registry, showInsertionPoint, isDragging, startDragging]), 200);
return (0,external_wp_compose_namespaceObject.__experimentalUseDropZone)({
// `currentTarget` is only available while the event is being
// handled, so get it now and pass it to the thottled function.
// https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
throttled(event, event.currentTarget.ownerDocument);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/index.js
const inner_blocks_EMPTY_OBJECT = {};
const context = useBlockContext(clientId);
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockContextProvider, {
const BlockListItemsMemo = (0,external_wp_element_namespaceObject.memo)(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) {
prioritizedInserterBlocks,
__experimentalDefaultBlock,
__experimentalDirectInsert,
templateInsertUpdatesSelection,
__experimentalCaptureToolbars: captureToolbars,
__experimentalAppenderTagName,
useNestedSettingsUpdate(clientId, parentLock, allowedBlocks, prioritizedInserterBlocks, defaultBlock, directInsert, __experimentalDefaultBlock, __experimentalDirectInsert, templateLock, captureToolbars, orientation, layout);
useInnerBlockTemplateSync(clientId, template, templateLock, templateInsertUpdatesSelection);
const defaultLayoutBlockSupport = (0,external_wp_blocks_namespaceObject.getBlockSupport)(name, 'layout') || (0,external_wp_blocks_namespaceObject.getBlockSupport)(name, '__experimentalLayout') || inner_blocks_EMPTY_OBJECT;
allowSizingOnChildren = false
} = defaultLayoutBlockSupport;
const usedLayout = layout || defaultLayoutBlockSupport;
const memoedLayout = (0,external_wp_element_namespaceObject.useMemo)(() => ({
// Default layout will know about any content/wide size defined by the theme.
...(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,external_ReactJSXRuntime_namespaceObject.jsx)(BlockListItemsMemo, {
renderAppender: renderAppender,
__experimentalAppenderTagName: __experimentalAppenderTagName,
if (Object.keys(blockType.providesContext).length === 0) {
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockContext, {
* 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) {
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(UncontrolledInnerBlocks, {
const ForwardedInnerBlocks = (0,external_wp_element_namespaceObject.forwardRef)((props, ref) => {
const innerBlocksProps = useInnerBlocksProps({
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
className: "block-editor-inner-blocks",
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
* 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.
* @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.
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md
function useInnerBlocksProps(props = {}, options = {}) {
__unstableDisableLayoutClassNames,
__unstableDisableDropZone,
__unstableLayoutClassNames: layoutClassNames = ''
} = useBlockEditContext();
const selected = (0,external_wp_data_namespaceObject.useSelect)(select => {
} = unlock(select(store));
// 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.
if (__unstableGetEditorMode() === 'zoom-out') {
} = unlock(getSettings());
_isDropZoneDisabled = clientId !== sectionRootClientId;
isDropZoneDisabled: _isDropZoneDisabled
} = select(external_wp_blocks_namespaceObject.store);
const blockName = getBlockName(clientId);
const enableClickThrough = __unstableGetEditorMode() === 'navigation';
const blockEditingMode = getBlockEditingMode(clientId);
const parentClientId = getBlockRootClientId(clientId);
const [defaultLayout] = getBlockSettings(clientId, 'layout');
if (_isDropZoneDisabled !== undefined) {
_isDropZoneDisabled = blockEditingMode === 'disabled';
__experimentalCaptureToolbars: hasBlockSupport(blockName, '__experimentalExposeControlsToChildren', false),
hasOverlay: blockName !== 'core/template' && !isBlockSelected(clientId) && !hasSelectedInnerBlock(clientId, true) && enableClickThrough && !isDragging(),
blockType: getBlockType(blockName),
parentLock: getTemplateLock(parentClientId),
isDropZoneDisabled: _isDropZoneDisabled,
__experimentalCaptureToolbars,
const blockDropZoneRef = useBlockDropZone({
const ref = (0,external_wp_compose_namespaceObject.useMergeRefs)([props.ref, __unstableDisableDropZone || isDropZoneDisabled ? null : blockDropZoneRef]);
const innerBlocksProps = {
__experimentalCaptureToolbars,
const InnerBlocks = innerBlocksProps.value && innerBlocksProps.onChange ? ControlledInnerBlocks : UncontrolledInnerBlocks;
className: dist_clsx(props.className, 'block-editor-block-list__layout', __unstableDisableLayoutClassNames ? '' : layoutClassNames, {
'has-overlay': hasOverlay
children: clientId ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(InnerBlocks, {
}) : /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockListItems, {
useInnerBlocksProps.save = external_wp_blocks_namespaceObject.__unstableGetInnerBlocksProps;
// Expose default appender placeholders as components.
ForwardedInnerBlocks.DefaultBlockAppender = default_block_appender;
ForwardedInnerBlocks.ButtonBlockAppender = inner_blocks_button_block_appender;
ForwardedInnerBlocks.Content = () => useInnerBlocksProps.save().children;
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md
/* harmony default export */ const inner_blocks = (ForwardedInnerBlocks);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/observe-typing/index.js