: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// If we're supposed to focus the block, we'll focus the first inner block
// otherwise, we won't apply any auto-focus.
// This ensures for instance that the focus stays in the inserter when inserting the "buttons" block.
getSelectedBlocksInitialCaretPosition());
}, [template, templateLock, clientId]);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/use-block-context.js
* Returns a context object for a given block.
* @param {string} clientId The block client ID.
* @return {Record<string,*>} Context value.
function useBlockContext(clientId) {
return (0,external_wp_data_namespaceObject.useSelect)(select => {
const block = select(store).getBlock(clientId);
const blockType = select(external_wp_blocks_namespaceObject.store).getBlockType(block.name);
if (Object.keys(blockType.providesContext).length === 0) {
return Object.fromEntries(Object.entries(blockType.providesContext).map(([contextName, attributeName]) => [contextName, block.attributes[attributeName]]));
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/use-on-block-drop/index.js
/** @typedef {import('react').SyntheticEvent} SyntheticEvent */
/** @typedef {import('./types').WPDropOperation} WPDropOperation */
* Retrieve the data for a block drop event.
* @param {SyntheticEvent} event The drop event.
* @return {Object} An object with block drag and drop data.
function parseDropEvent(event) {
if (!event.dataTransfer) {
result = Object.assign(result, JSON.parse(event.dataTransfer.getData('wp-blocks')));
* A function that returns an event handler function for block drop events.
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
* @param {Function} getBlockIndex A function that gets the index of a block.
* @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks.
* @param {Function} moveBlocks A function that moves blocks.
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
* @param {Function} clearSelectedBlock A function that clears block selection.
* @param {string} operation The type of operation to perform on drop. Could be `insert` or `replace` or `group`.
* @param {Function} getBlock A function that returns a block given its client id.
* @return {Function} The event handler for a block drop event.
function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants, moveBlocks, insertOrReplaceBlocks, clearSelectedBlock, operation, getBlock) {
srcRootClientId: sourceRootClientId,
srcClientIds: sourceClientIds,
} = parseDropEvent(event);
// If the user is inserting a block.
if (dropType === 'inserter') {
const blocksToInsert = blocks.map(block => (0,external_wp_blocks_namespaceObject.cloneBlock)(block));
insertOrReplaceBlocks(blocksToInsert, true, null);
// If the user is moving a block.
if (dropType === 'block') {
const sourceBlockIndex = getBlockIndex(sourceClientIds[0]);
// If the user is dropping to the same position, return early.
if (sourceRootClientId === targetRootClientId && sourceBlockIndex === targetBlockIndex) {
// If the user is attempting to drop a block within its own
// nested blocks, return early as this would create infinite
if (sourceClientIds.includes(targetRootClientId) || getClientIdsOfDescendants(sourceClientIds).some(id => id === targetRootClientId)) {
// If the user is dropping a block over another block, replace both blocks
// with a group block containing them
if (operation === 'group') {
const blocksToInsert = sourceClientIds.map(clientId => getBlock(clientId));
insertOrReplaceBlocks(blocksToInsert, true, null, sourceClientIds);
const isAtSameLevel = sourceRootClientId === targetRootClientId;
const draggedBlockCount = sourceClientIds.length;
// If the block is kept at the same level and moved downwards,
// subtract to take into account that the blocks being dragged
// were removed from the block list above the insertion point.
const insertIndex = isAtSameLevel && sourceBlockIndex < targetBlockIndex ? targetBlockIndex - draggedBlockCount : targetBlockIndex;
moveBlocks(sourceClientIds, sourceRootClientId, insertIndex);
* A function that returns an event handler function for block-related file drop events.
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
* @param {Function} getSettings A function that gets the block editor settings.
* @param {Function} updateBlockAttributes A function that updates a block's attributes.
* @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted.
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
* @return {Function} The event handler for a block-related file drop event.
function onFilesDrop(targetRootClientId, getSettings, updateBlockAttributes, canInsertBlockType, insertOrReplaceBlocks) {
if (!getSettings().mediaUpload) {
const transformation = (0,external_wp_blocks_namespaceObject.findTransform)((0,external_wp_blocks_namespaceObject.getBlockTransforms)('from'), transform => transform.type === 'files' && canInsertBlockType(transform.blockName, targetRootClientId) && transform.isMatch(files));
const blocks = transformation.transform(files, updateBlockAttributes);
insertOrReplaceBlocks(blocks);
* A function that returns an event handler function for block-related HTML drop events.
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
* @return {Function} The event handler for a block-related HTML drop event.
function onHTMLDrop(insertOrReplaceBlocks) {
const blocks = (0,external_wp_blocks_namespaceObject.pasteHandler)({
insertOrReplaceBlocks(blocks);
* A React hook for handling block drop events.
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
* @param {Object} options The optional options.
* @param {WPDropOperation} [options.operation] The type of operation to perform on drop. Could be `insert` or `replace` for now.
* @return {Function} A function to be passed to the onDrop handler.
function useOnBlockDrop(targetRootClientId, targetBlockIndex, options = {}) {
getClientIdsOfDescendants,
} = (0,external_wp_data_namespaceObject.useSelect)(store);
} = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blocks_namespaceObject.store);
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
const registry = (0,external_wp_data_namespaceObject.useRegistry)();
const insertOrReplaceBlocks = (0,external_wp_element_namespaceObject.useCallback)((blocks, updateSelection = true, initialPosition = 0, clientIdsToReplace = []) => {
if (!Array.isArray(blocks)) {
const clientIds = getBlockOrder(targetRootClientId);
const clientId = clientIds[targetBlockIndex];
const blocksClientIds = blocks.map(block => block.clientId);
const areGroupableBlocks = isGroupable([...blocksClientIds, clientId]);
if (operation === 'replace') {
replaceBlocks(clientId, blocks, undefined, initialPosition);
} else if (operation === 'group' && areGroupableBlocks) {
const targetBlock = getBlock(clientId);
if (nearestSide === 'left') {
blocks.push(targetBlock);
blocks.unshift(targetBlock);
const groupInnerBlocks = blocks.map(block => {
return (0,external_wp_blocks_namespaceObject.createBlock)(block.name, block.attributes, block.innerBlocks);
const areAllImages = blocks.every(block => {
return block.name === 'core/image';
const galleryBlock = canInsertBlockType('core/gallery', targetRootClientId);
const wrappedBlocks = (0,external_wp_blocks_namespaceObject.createBlock)(areAllImages && galleryBlock ? 'core/gallery' : getGroupingBlockName(), {
flexWrap: areAllImages && galleryBlock ? null : 'nowrap'
// Need to make sure both the target block and the block being dragged are replaced
// otherwise the dragged block will be duplicated.
replaceBlocks([clientId, ...clientIdsToReplace], wrappedBlocks, undefined, initialPosition);
insertBlocks(blocks, targetBlockIndex, targetRootClientId, updateSelection, initialPosition);
}, [getBlockOrder, targetRootClientId, targetBlockIndex, isGroupable, operation, replaceBlocks, getBlock, nearestSide, canInsertBlockType, getGroupingBlockName, insertBlocks]);
const moveBlocks = (0,external_wp_element_namespaceObject.useCallback)((sourceClientIds, sourceRootClientId, insertIndex) => {
if (operation === 'replace') {
const sourceBlocks = getBlocksByClientId(sourceClientIds);
const targetBlockClientIds = getBlockOrder(targetRootClientId);
const targetBlockClientId = targetBlockClientIds[targetBlockIndex];
// Remove the source blocks.
removeBlocks(sourceClientIds, false);
// Replace the target block with the source blocks.
replaceBlocks(targetBlockClientId, sourceBlocks, undefined, 0);
moveBlocksToPosition(sourceClientIds, sourceRootClientId, targetRootClientId, insertIndex);
}, [operation, getBlockOrder, getBlocksByClientId, moveBlocksToPosition, registry, removeBlocks, replaceBlocks, targetBlockIndex, targetRootClientId]);
const _onDrop = onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants, moveBlocks, insertOrReplaceBlocks, clearSelectedBlock, operation, getBlock);
const _onFilesDrop = onFilesDrop(targetRootClientId, getSettings, updateBlockAttributes, canInsertBlockType, insertOrReplaceBlocks);
const _onHTMLDrop = onHTMLDrop(insertOrReplaceBlocks);
const files = (0,external_wp_dom_namespaceObject.getFilesFromDataTransfer)(event.dataTransfer);
const html = event.dataTransfer.getData('text/html');
* From Windows Chrome 96, the `event.dataTransfer` returns both file object and HTML.
* The order of the checks is important to recognise the HTML drop.
} else if (files.length) {
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/utils/math.js
* A string representing the name of an edge.
* @typedef {'top'|'right'|'bottom'|'left'} WPEdgeName
* @typedef {Object} WPPoint
* @property {number} x The horizontal position.
* @property {number} y The vertical position.
* Given a point, a DOMRect and the name of an edge, returns the distance to
* This function works for edges that are horizontal or vertical (e.g. not
* rotated), the following terms are used so that the function works in both
* - Forward, meaning the axis running horizontally when an edge is vertical
* and vertically when an edge is horizontal.
* - Lateral, meaning the axis running vertically when an edge is vertical
* and horizontally when an edge is horizontal.
* @param {WPPoint} point The point to measure distance from.
* @param {DOMRect} rect A DOM Rect containing edge positions.
* @param {WPEdgeName} edge The edge to measure to.
function getDistanceFromPointToEdge(point, rect, edge) {
const isHorizontal = edge === 'top' || edge === 'bottom';
const pointLateralPosition = isHorizontal ? x : y;
const pointForwardPosition = isHorizontal ? y : x;
const edgeStart = isHorizontal ? rect.left : rect.top;
const edgeEnd = isHorizontal ? rect.right : rect.bottom;
const edgeForwardPosition = rect[edge];
// Measure the straight line distance to the edge of the rect, when the
// point is adjacent to the edge.
// Else, if the point is positioned diagonally to the edge of the rect,
// measure diagonally to the nearest corner that the edge meets.
if (pointLateralPosition >= edgeStart && pointLateralPosition <= edgeEnd) {
edgeLateralPosition = pointLateralPosition;
} else if (pointLateralPosition < edgeEnd) {
edgeLateralPosition = edgeStart;
edgeLateralPosition = edgeEnd;
return Math.sqrt((pointLateralPosition - edgeLateralPosition) ** 2 + (pointForwardPosition - edgeForwardPosition) ** 2);
* Given a point, a DOMRect and a list of allowed edges returns the name of and
* distance to the nearest edge.
* @param {WPPoint} point The point to measure distance from.
* @param {DOMRect} rect A DOM Rect containing edge positions.
* @param {WPEdgeName[]} allowedEdges A list of the edges included in the
* calculation. Defaults to all edges.
* @return {[number, string]} An array where the first value is the distance
* and a second is the edge name.
function getDistanceToNearestEdge(point, rect, allowedEdges = ['top', 'bottom', 'left', 'right']) {
allowedEdges.forEach(edge => {
const distance = getDistanceFromPointToEdge(point, rect, edge);
if (candidateDistance === undefined || distance < candidateDistance) {
candidateDistance = distance;
return [candidateDistance, candidateEdge];
* Is the point contained by the rectangle.
* @param {WPPoint} point The point.
* @param {DOMRect} rect The rectangle.
* @return {boolean} True if the point is contained by the rectangle, false otherwise.
function isPointContainedByRect(point, rect) {
return rect.left <= point.x && rect.right >= point.x && rect.top <= point.y && rect.bottom >= point.y;
* Is the point within the top and bottom boundaries of the rectangle.
* @param {WPPoint} point The point.
* @param {DOMRect} rect The rectangle.
* @return {boolean} True if the point is within top and bottom of rectangle, false otherwise.
function isPointWithinTopAndBottomBoundariesOfRect(point, rect) {
return rect.top <= point.y && rect.bottom >= point.y;
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/use-block-drop-zone/index.js
const THRESHOLD_DISTANCE = 30;
const MINIMUM_HEIGHT_FOR_THRESHOLD = 120;
const MINIMUM_WIDTH_FOR_THRESHOLD = 120;
/** @typedef {import('../../utils/math').WPPoint} WPPoint */
/** @typedef {import('../use-on-block-drop/types').WPDropOperation} WPDropOperation */
* The orientation of a block list.
* @typedef {'horizontal'|'vertical'|undefined} WPBlockListOrientation
* The insert position when dropping a block.
* @typedef {'before'|'after'} WPInsertPosition
* @typedef {Object} WPBlockData
* @property {boolean} isUnmodifiedDefaultBlock Is the block unmodified default block.
* @property {() => DOMRect} getBoundingClientRect Get the bounding client rect of the block.
* @property {number} blockIndex The index of the block.
* Get the drop target position from a given drop point and the orientation.
* @param {WPBlockData[]} blocksData The block data list.
* @param {WPPoint} position The position of the item being dragged.
* @param {WPBlockListOrientation} orientation The orientation of the block list.
* @param {Object} options Additional options.
* @return {[number, WPDropOperation]} The drop target position.
function getDropTargetPosition(blocksData, position, orientation = 'vertical', options = {}) {
const allowedEdges = orientation === 'horizontal' ? ['left', 'right'] : ['top', 'bottom'];
let insertPosition = 'before';
let minDistance = Infinity;
let targetBlockIndex = null;
let nearestSide = 'right';
// Allow before/after when dragging over the top/bottom edges of the drop zone.
if (dropZoneElement && parentBlockOrientation !== 'horizontal') {
const rect = dropZoneElement.getBoundingClientRect();
const [distance, edge] = getDistanceToNearestEdge(position, rect, ['top', 'bottom']);
// If dragging over the top or bottom 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 or Cover.
if (rect.height > MINIMUM_HEIGHT_FOR_THRESHOLD && distance < THRESHOLD_DISTANCE) {
return [rootBlockIndex, 'before'];
return [rootBlockIndex + 1, 'after'];
const isRightToLeft = (0,external_wp_i18n_namespaceObject.isRTL)();
// Allow before/after when dragging over the left/right edges of the drop zone.