: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// vertical position of the visible content area, plus the height
const restrictedTopArea = topOfContentElementInViewport + toolbarHeight;
const hasSpaceForToolbarAbove = blockRect.top > restrictedTopArea;
const isBlockTallerThanViewport = blockRect.height > viewportHeight - toolbarHeight;
// Sticky blocks are treated as if they will never have enough space for the toolbar above.
if (!isSticky && (hasSpaceForToolbarAbove || isBlockTallerThanViewport)) {
return RESTRICTED_HEIGHT_PROPS;
* Determines the desired popover positioning behavior, returning a set of appropriate props.
* @param {Object} elements
* @param {Element} elements.contentElement The DOM element that represents the editor content or canvas.
* @param {string} elements.clientId The clientId of the first selected block.
* @return {Object} The popover props used to determine the position of the toolbar.
function useBlockToolbarPopoverProps({
const selectedBlockElement = useBlockElement(clientId);
const [toolbarHeight, setToolbarHeight] = (0,external_wp_element_namespaceObject.useState)(0);
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
blockIndex: getBlockIndex(clientId),
isSticky: hasStickyOrFixedPositionValue(getBlockAttributes(clientId))
const scrollContainer = (0,external_wp_element_namespaceObject.useMemo)(() => {
return (0,external_wp_dom_namespaceObject.getScrollContainer)(contentElement);
const [props, setProps] = (0,external_wp_element_namespaceObject.useState)(() => getProps(contentElement, selectedBlockElement, scrollContainer, toolbarHeight, isSticky));
const popoverRef = (0,external_wp_compose_namespaceObject.useRefEffect)(popoverNode => {
setToolbarHeight(popoverNode.offsetHeight);
const updateProps = (0,external_wp_element_namespaceObject.useCallback)(() => setProps(getProps(contentElement, selectedBlockElement, scrollContainer, toolbarHeight, isSticky)), [contentElement, selectedBlockElement, scrollContainer, toolbarHeight]);
// Update props when the block is moved. This also ensures the props are
// correct on initial mount, and when the selected block or content element
// changes (since the callback ref will update).
(0,external_wp_element_namespaceObject.useLayoutEffect)(updateProps, [blockIndex, updateProps]);
// Update props when the viewport is resized or the block is resized.
(0,external_wp_element_namespaceObject.useLayoutEffect)(() => {
if (!contentElement || !selectedBlockElement) {
// Update the toolbar props on viewport resize.
const contentView = contentElement?.ownerDocument?.defaultView;
contentView?.addEventHandler?.('resize', updateProps);
// Update the toolbar props on block resize.
const blockView = selectedBlockElement?.ownerDocument?.defaultView;
if (blockView.ResizeObserver) {
resizeObserver = new blockView.ResizeObserver(updateProps);
resizeObserver.observe(selectedBlockElement);
contentView?.removeEventHandler?.('resize', updateProps);
resizeObserver.disconnect();
}, [updateProps, contentElement, selectedBlockElement]);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-tools/use-selected-block-tool-props.js
* Returns props for the selected block tools and empty block inserter.
* @param {string} clientId Selected block client ID.
function useSelectedBlockToolProps(clientId) {
const selectedBlockProps = (0,external_wp_data_namespaceObject.useSelect)(select => {
__experimentalGetBlockListSettingsForBlocks,
isBlockInsertionPointVisible,
getLastMultiSelectedBlockClientId
const blockParentsClientIds = getBlockParents(clientId);
// Get Block List Settings for all ancestors of the current Block clientId.
const parentBlockListSettings = __experimentalGetBlockListSettingsForBlocks(blockParentsClientIds);
// Get the clientId of the topmost parent with the capture toolbars setting.
const capturingClientId = blockParentsClientIds.find(parentClientId => parentBlockListSettings[parentClientId]?.__experimentalCaptureToolbars);
let isInsertionPointVisible = false;
if (isBlockInsertionPointVisible()) {
const insertionPoint = getBlockInsertionPoint();
const order = getBlockOrder(insertionPoint.rootClientId);
isInsertionPointVisible = order[insertionPoint.index] === clientId;
lastClientId: hasMultiSelection() ? getLastMultiSelectedBlockClientId() : null,
rootClientId: getBlockRootClientId(clientId)
return selectedBlockProps;
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-tools/empty-block-inserter.js
function EmptyBlockInserter({
} = useSelectedBlockToolProps(clientId);
const popoverProps = useBlockToolbarPopoverProps({
contentElement: __unstableContentRef?.current,
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(cover, {
clientId: capturingClientId || clientId,
bottomClientId: lastClientId,
className: dist_clsx('block-editor-block-list__block-side-inserter-popover', {
'is-insertion-point-visible': isInsertionPointVisible
__unstableContentRef: __unstableContentRef,
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
className: "block-editor-block-list__empty-block-inserter",
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter, {
position: "bottom right",
rootClientId: rootClientId,
__experimentalIsQuick: true
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-draggable/use-scroll-when-dragging.js
const SCROLL_INACTIVE_DISTANCE_PX = 50;
const SCROLL_INTERVAL_MS = 25;
const PIXELS_PER_SECOND_PER_PERCENTAGE = 1000;
const VELOCITY_MULTIPLIER = PIXELS_PER_SECOND_PER_PERCENTAGE * (SCROLL_INTERVAL_MS / 1000);
* React hook that scrolls the scroll container when a block is being dragged.
* @return {Function[]} `startScrolling`, `scrollOnDragOver`, `stopScrolling`
* functions to be called in `onDragStart`, `onDragOver`
* and `onDragEnd` events respectively.
function useScrollWhenDragging() {
const dragStartY = (0,external_wp_element_namespaceObject.useRef)(null);
const velocityY = (0,external_wp_element_namespaceObject.useRef)(null);
const scrollParentY = (0,external_wp_element_namespaceObject.useRef)(null);
const scrollEditorInterval = (0,external_wp_element_namespaceObject.useRef)(null);
// Clear interval when unmounting.
(0,external_wp_element_namespaceObject.useEffect)(() => () => {
if (scrollEditorInterval.current) {
clearInterval(scrollEditorInterval.current);
scrollEditorInterval.current = null;
const startScrolling = (0,external_wp_element_namespaceObject.useCallback)(event => {
dragStartY.current = event.clientY;
// Find nearest parent(s) to scroll.
scrollParentY.current = (0,external_wp_dom_namespaceObject.getScrollContainer)(event.target);
scrollEditorInterval.current = setInterval(() => {
if (scrollParentY.current && velocityY.current) {
const newTop = scrollParentY.current.scrollTop + velocityY.current;
// Setting `behavior: 'smooth'` as a scroll property seems to hurt performance.
// Better to use a small scroll interval.
scrollParentY.current.scroll({
const scrollOnDragOver = (0,external_wp_element_namespaceObject.useCallback)(event => {
if (!scrollParentY.current) {
const scrollParentHeight = scrollParentY.current.offsetHeight;
const offsetDragStartPosition = dragStartY.current - scrollParentY.current.offsetTop;
const offsetDragPosition = event.clientY - scrollParentY.current.offsetTop;
if (event.clientY > offsetDragStartPosition) {
// User is dragging downwards.
const moveableDistance = Math.max(scrollParentHeight - offsetDragStartPosition - SCROLL_INACTIVE_DISTANCE_PX, 0);
const dragDistance = Math.max(offsetDragPosition - offsetDragStartPosition - SCROLL_INACTIVE_DISTANCE_PX, 0);
const distancePercentage = moveableDistance === 0 || dragDistance === 0 ? 0 : dragDistance / moveableDistance;
velocityY.current = VELOCITY_MULTIPLIER * distancePercentage;
} else if (event.clientY < offsetDragStartPosition) {
// User is dragging upwards.
const moveableDistance = Math.max(offsetDragStartPosition - SCROLL_INACTIVE_DISTANCE_PX, 0);
const dragDistance = Math.max(offsetDragStartPosition - offsetDragPosition - SCROLL_INACTIVE_DISTANCE_PX, 0);
const distancePercentage = moveableDistance === 0 || dragDistance === 0 ? 0 : dragDistance / moveableDistance;
velocityY.current = -VELOCITY_MULTIPLIER * distancePercentage;
const stopScrolling = () => {
dragStartY.current = null;
scrollParentY.current = null;
if (scrollEditorInterval.current) {
clearInterval(scrollEditorInterval.current);
scrollEditorInterval.current = null;
return [startScrolling, scrollOnDragOver, stopScrolling];
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-draggable/index.js
const BlockDraggable = ({
fadeWhenDisabled = false,
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
isBlockInsertionPointVisible
getBlockType: _getBlockType,
} = select(external_wp_blocks_namespaceObject.store);
const rootClientId = getBlockRootClientId(clientIds[0]);
const blockName = getBlockName(clientIds[0]);
const variation = getActiveBlockVariation(blockName, getBlockAttributes(clientIds[0]));
srcRootClientId: rootClientId,
isDraggable: canMoveBlocks(clientIds),
icon: variation?.icon || _getBlockType(blockName)?.icon,
visibleInserter: isBlockInsertionPointVisible(),
getBlockType: _getBlockType
const isDragging = (0,external_wp_element_namespaceObject.useRef)(false);
const [startScrolling, scrollOnDragOver, stopScrolling] = useScrollWhenDragging();
} = (0,external_wp_data_namespaceObject.useSelect)(store);
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
// Stop dragging blocks if the block draggable is unmounted.
(0,external_wp_element_namespaceObject.useEffect)(() => {
if (isDragging.current) {
// Find the root of the editor iframe.
const blockRef = useBlockRef(clientIds[0]);
const editorRoot = blockRef.current?.closest('body');
* Add a dragover event listener to the editor root to track the blocks being dragged over.
* The listener has to be inside the editor iframe otherwise the target isn't accessible.
(0,external_wp_element_namespaceObject.useEffect)(() => {
if (!editorRoot || !fadeWhenDisabled) {
const onDragOver = event => {
if (!event.target.closest('[data-block]')) {
const draggedBlockNames = getBlockNamesByClientId(clientIds);
const targetClientId = event.target.closest('[data-block]').getAttribute('data-block');
const allowedBlocks = getAllowedBlocks(targetClientId);
const targetBlockName = getBlockNamesByClientId([targetClientId])[0];
* Check if the target is valid to drop in.
* If the target's allowedBlocks is an empty array,
* it isn't a container block, in which case we check
* its parent's validity instead.
if (allowedBlocks?.length === 0) {
const targetRootClientId = getBlockRootClientId(targetClientId);
const targetRootBlockName = getBlockNamesByClientId([targetRootClientId])[0];
const rootAllowedBlocks = getAllowedBlocks(targetRootClientId);
dropTargetValid = isDropTargetValid(getBlockType, rootAllowedBlocks, draggedBlockNames, targetRootBlockName);
dropTargetValid = isDropTargetValid(getBlockType, allowedBlocks, draggedBlockNames, targetBlockName);
* Update the body class to reflect if drop target is valid.
* This has to be done on the document body because the draggable
* chip is rendered outside of the editor iframe.
if (!dropTargetValid && !visibleInserter) {
window?.document?.body?.classList?.add('block-draggable-invalid-drag-token');
window?.document?.body?.classList?.remove('block-draggable-invalid-drag-token');
const throttledOnDragOver = (0,external_wp_compose_namespaceObject.throttle)(onDragOver, 200);
editorRoot.addEventListener('dragover', throttledOnDragOver);
editorRoot.removeEventListener('dragover', throttledOnDragOver);
}, [clientIds, editorRoot, fadeWhenDisabled, getAllowedBlocks, getBlockNamesByClientId, getBlockRootClientId, getBlockType, visibleInserter]);
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Draggable, {
appendToOwnerDocument: appendToOwnerDocument,
cloneClassname: cloneClassname,
__experimentalTransferDataType: "wp-blocks",
transferData: transferData,
// Defer hiding the dragged source element to the next
// frame to enable dragging.
window.requestAnimationFrame(() => {
startDraggingBlocks(clientIds);
isDragging.current = true;
onDragOver: scrollOnDragOver,
isDragging.current = false;
__experimentalDragComponent:
// Check against `undefined` so that `null` can be used to disable
// the default drag component.
dragComponent !== undefined ? dragComponent : /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockDraggableChip, {
onDragStart: onDraggableStart,
onDragEnd: onDraggableEnd
/* harmony default export */ const block_draggable = (BlockDraggable);
;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/chevron-up.js
const chevronUp = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, {
xmlns: "http://www.w3.org/2000/svg",
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, {
d: "M6.5 12.4L12 8l5.5 4.4-.9 1.2L12 10l-4.5 3.6-1-1.2z"
/* harmony default export */ const chevron_up = (chevronUp);
;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/chevron-down.js
const chevronDown = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, {
xmlns: "http://www.w3.org/2000/svg",
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, {
d: "M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"
/* harmony default export */ const chevron_down = (chevronDown);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-mover/mover-description.js
const getMovementDirection = (moveDirection, orientation) => {
if (moveDirection === 'up') {
if (orientation === 'horizontal') {