: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
clientIds: selectedBlockParentClientIds
}, [firstSelectedBlockClientId, selectedBlockParentClientIds, selectedTreeId, setExpandedState]);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/list-view/use-clipboard-handler.js
// This hook borrows from useClipboardHandler in ../writing-flow/use-clipboard-handler.js
// and adds behaviour for the list view, while skipping partial selection.
function use_clipboard_handler_useClipboardHandler({
const registry = (0,external_wp_data_namespaceObject.useRegistry)();
getPreviousBlockClientId,
getSelectedBlockClientIds,
} = (0,external_wp_data_namespaceObject.useSelect)(store);
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
const notifyCopy = useNotifyCopy();
return (0,external_wp_compose_namespaceObject.useRefEffect)(node => {
function updateFocusAndSelection(focusClientId, shouldSelectBlock) {
selectBlock(undefined, focusClientId, null, null);
focusListItem(focusClientId, node);
// Determine which blocks to update:
// If the current (focused) block is part of the block selection, use the whole selection.
// If the focused block is not part of the block selection, only update the focused block.
function getBlocksToUpdate(clientId) {
const selectedBlockClientIds = getSelectedBlockClientIds();
const isUpdatingSelectedBlocks = selectedBlockClientIds.includes(clientId);
const firstBlockClientId = isUpdatingSelectedBlocks ? selectedBlockClientIds[0] : clientId;
const firstBlockRootClientId = getBlockRootClientId(firstBlockClientId);
const blocksToUpdate = isUpdatingSelectedBlocks ? selectedBlockClientIds : [clientId];
originallySelectedBlockClientIds: selectedBlockClientIds
function handler(event) {
if (event.defaultPrevented) {
// This was possibly already handled in rich-text/use-paste-handler.js.
// Only handle events that occur within the list view.
if (!node.contains(event.target.ownerDocument.activeElement)) {
// Retrieve the block clientId associated with the focused list view row.
// This enables applying copy / cut / paste behavior to the focused block,
// rather than just the blocks that are currently selected.
const listViewRow = event.target.ownerDocument.activeElement?.closest('[role=row]');
const clientId = listViewRow?.dataset?.block;
blocksToUpdate: selectedBlockClientIds,
originallySelectedBlockClientIds
} = getBlocksToUpdate(clientId);
if (selectedBlockClientIds.length === 0) {
if (event.type === 'copy' || event.type === 'cut') {
if (selectedBlockClientIds.length === 1) {
flashBlock(selectedBlockClientIds[0]);
notifyCopy(event.type, selectedBlockClientIds);
const blocks = getBlocksByClientId(selectedBlockClientIds);
setClipboardBlocks(event, blocks, registry);
if (event.type === 'cut') {
var _getPreviousBlockClie;
// Don't update the selection if the blocks cannot be deleted.
if (!canRemoveBlocks(selectedBlockClientIds)) {
let blockToFocus = (_getPreviousBlockClie = getPreviousBlockClientId(firstBlockClientId)) !== null && _getPreviousBlockClie !== void 0 ? _getPreviousBlockClie :
// If the previous block is not found (when the first block is deleted),
// fallback to focus the parent block.
// Remove blocks, but don't update selection, and it will be handled below.
removeBlocks(selectedBlockClientIds, false);
// Update the selection if the original selection has been removed.
const shouldUpdateSelection = originallySelectedBlockClientIds.length > 0 && getSelectedBlockClientIds().length === 0;
// If there's no previous block nor parent block, focus the first block.
blockToFocus = getBlockOrder()[0];
updateFocusAndSelection(blockToFocus, shouldUpdateSelection);
} else if (event.type === 'paste') {
__experimentalCanUserUseUnfilteredHTML: canUserUseUnfilteredHTML
const blocks = getPasteBlocks(event, canUserUseUnfilteredHTML);
if (selectedBlockClientIds.length === 1) {
const [selectedBlockClientId] = selectedBlockClientIds;
// If a single block is focused, and the blocks to be posted can
// be inserted within the block, then append the pasted blocks
// within the focused block. For example, if you have copied a paragraph
// block and paste it within a single Group block, this will append
// the paragraph block within the Group block.
if (blocks.every(block => canInsertBlockType(block.name, selectedBlockClientId))) {
insertBlocks(blocks, undefined, selectedBlockClientId);
updateFocusAndSelection(blocks[0]?.clientId, false);
replaceBlocks(selectedBlockClientIds, blocks, blocks.length - 1, -1);
updateFocusAndSelection(blocks[0]?.clientId, false);
node.ownerDocument.addEventListener('copy', handler);
node.ownerDocument.addEventListener('cut', handler);
node.ownerDocument.addEventListener('paste', handler);
node.ownerDocument.removeEventListener('copy', handler);
node.ownerDocument.removeEventListener('cut', handler);
node.ownerDocument.removeEventListener('paste', handler);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/list-view/index.js
const expanded = (state, action) => {
if (action.type === 'clear') {
if (Array.isArray(action.clientIds)) {
...action.clientIds.reduce((newState, id) => ({
[id]: action.type === 'expand'
const BLOCK_LIST_ITEM_HEIGHT = 32;
/** @typedef {import('react').ComponentType} ComponentType */
/** @typedef {import('react').Ref<HTMLElement>} Ref */
* Show a hierarchical list of blocks.
* @param {Object} props Components props.
* @param {string} props.id An HTML element id for the root element of ListView.
* @param {Array} props.blocks _deprecated_ Custom subset of block client IDs to be used instead of the default hierarchy.
* @param {?HTMLElement} props.dropZoneElement Optional element to be used as the drop zone.
* @param {?boolean} props.showBlockMovers Flag to enable block movers. Defaults to `false`.
* @param {?boolean} props.isExpanded Flag to determine whether nested levels are expanded by default. Defaults to `false`.
* @param {?boolean} props.showAppender Flag to show or hide the block appender. Defaults to `false`.
* @param {?ComponentType} props.blockSettingsMenu Optional more menu substitution. Defaults to the standard `BlockSettingsDropdown` component.
* @param {string} props.rootClientId The client id of the root block from which we determine the blocks to show in the list.
* @param {string} props.description Optional accessible description for the tree grid component.
* @param {?Function} props.onSelect Optional callback to be invoked when a block is selected. Receives the block object that was selected.
* @param {?ComponentType} props.additionalBlockContent Component that renders additional block content UI.
* @param {Ref} ref Forwarded ref
function ListViewComponent({
blockSettingsMenu: BlockSettingsMenu = BlockSettingsDropdown,
additionalBlockContent: AdditionalBlockContent
// This can be removed once we no longer need to support the blocks prop.
external_wp_deprecated_default()('`blocks` property in `wp.blockEditor.__experimentalListView`', {
alternative: '`rootClientId` property'
const instanceId = (0,external_wp_compose_namespaceObject.useInstanceId)(ListViewComponent);
} = useListViewClientIds({
const blockIndexes = useListViewBlockIndexes(clientIdsTree);
} = (0,external_wp_data_namespaceObject.useSelect)(store);
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
getClientIdsOfDescendants,
const draggedBlockCount = draggedClientIds?.length > 0 ? getClientIdsOfDescendants(draggedClientIds).length + 1 : 0;
visibleBlockCount: getGlobalBlockCount() - draggedBlockCount,
shouldShowInnerBlocks: __unstableGetEditorMode() !== 'zoom-out'
const [expandedState, setExpandedState] = (0,external_wp_element_namespaceObject.useReducer)(expanded, {});
const [insertedBlock, setInsertedBlock] = (0,external_wp_element_namespaceObject.useState)(null);
} = useListViewExpandSelectedItem({
firstSelectedBlockClientId: selectedClientIds[0],
const selectEditorBlock = (0,external_wp_element_namespaceObject.useCallback)(
* @param {MouseEvent | KeyboardEvent | undefined} event
* @param {string} blockClientId
* @param {null | undefined | -1 | 1} focusPosition
(event, blockClientId, focusPosition) => {
updateBlockSelection(event, blockClientId, null, focusPosition);
setSelectedTreeId(blockClientId);
onSelect(getBlock(blockClientId));
}, [setSelectedTreeId, updateBlockSelection, onSelect, getBlock]);
} = useListViewDropZone({
const elementRef = (0,external_wp_element_namespaceObject.useRef)();
// Allow handling of copy, cut, and paste events.
const clipBoardRef = use_clipboard_handler_useClipboardHandler({
selectBlock: selectEditorBlock
const treeGridRef = (0,external_wp_compose_namespaceObject.useMergeRefs)([clipBoardRef, elementRef, dropZoneRef, ref]);
(0,external_wp_element_namespaceObject.useEffect)(() => {
// If a blocks are already selected when the list view is initially
// mounted, shift focus to the first selected block.
if (selectedClientIds?.length) {
focusListItem(selectedClientIds[0], elementRef?.current);
// Disable reason: Only focus on the selected item when the list view is mounted.
// eslint-disable-next-line react-hooks/exhaustive-deps
const expand = (0,external_wp_element_namespaceObject.useCallback)(clientId => {
const clientIds = Array.isArray(clientId) ? clientId : [clientId];
const collapse = (0,external_wp_element_namespaceObject.useCallback)(clientId => {
const collapseAll = (0,external_wp_element_namespaceObject.useCallback)(() => {
const expandRow = (0,external_wp_element_namespaceObject.useCallback)(row => {
expand(row?.dataset?.block);
const collapseRow = (0,external_wp_element_namespaceObject.useCallback)(row => {
collapse(row?.dataset?.block);
const focusRow = (0,external_wp_element_namespaceObject.useCallback)((event, startRow, endRow) => {
updateBlockSelection(event, startRow?.dataset?.block, endRow?.dataset?.block);
}, [updateBlockSelection]);
useListViewCollapseItems({
const firstDraggedBlockClientId = draggedClientIds?.[0];
// Convert a blockDropTarget into indexes relative to the blocks in the list view.
// These values are used to determine which blocks should be displaced to make room
// for the drop indicator. See `ListViewBranch` and `getDragDisplacementValues`.
} = (0,external_wp_element_namespaceObject.useMemo)(() => {
let _blockDropTargetIndex, _firstDraggedBlockIndex;
if (blockDropTarget?.clientId) {
const foundBlockIndex = blockIndexes[blockDropTarget.clientId];
// If dragging below or inside the block, treat the drop target as the next block.
_blockDropTargetIndex = foundBlockIndex === undefined || blockDropTarget?.dropPosition === 'top' ? foundBlockIndex : foundBlockIndex + 1;
} else if (blockDropTarget === null) {
// A `null` value is used to indicate that the user is dragging outside of the list view.
_blockDropTargetIndex = null;
if (firstDraggedBlockClientId) {
const foundBlockIndex = blockIndexes[firstDraggedBlockClientId];
_firstDraggedBlockIndex = foundBlockIndex === undefined || blockDropTarget?.dropPosition === 'top' ? foundBlockIndex : foundBlockIndex + 1;
blockDropTargetIndex: _blockDropTargetIndex,
blockDropPosition: blockDropTarget?.dropPosition,
firstDraggedBlockIndex: _firstDraggedBlockIndex
}, [blockDropTarget, blockIndexes, firstDraggedBlockClientId]);
const contextValue = (0,external_wp_element_namespaceObject.useMemo)(() => ({
listViewInstanceId: instanceId,
treeGridElementRef: elementRef,
}), [blockDropPosition, blockDropTargetIndex, blockIndexes, draggedClientIds, expandedState, expand, firstDraggedBlockIndex, collapse, collapseAll, BlockSettingsMenu, instanceId, AdditionalBlockContent, insertedBlock, setInsertedBlock, rootClientId]);
// List View renders a fixed number of items and relies on each having a fixed item height of 36px.
// If this value changes, we should also change the itemHeight value set in useFixedWindowList.
// See: https://github.com/WordPress/gutenberg/pull/35230 for additional context.
const [fixedListWindow] = (0,external_wp_compose_namespaceObject.__experimentalUseFixedWindowList)(elementRef, BLOCK_LIST_ITEM_HEIGHT, visibleBlockCount, {
// Ensure that the windowing logic is recalculated when the expanded state changes.
// This is necessary because expanding a collapsed block in a short list view can
// switch the list view to a tall list view with a scrollbar, and vice versa.
// When this happens, the windowing logic needs to be recalculated to ensure that
// the correct number of blocks are rendered, by rechecking for a scroll container.
// If there are no blocks to show and we're not showing the appender, do not render the list view.
if (!clientIdsTree.length && !showAppender) {
const describedById = description && `block-editor-list-view-description-${instanceId}`;
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_data_namespaceObject.AsyncModeProvider, {
children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ListViewDropIndicatorPreview, {
draggedBlockClientId: firstDraggedBlockClientId,
blockDropTarget: blockDropTarget
}), description && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.VisuallyHidden, {
}), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalTreeGrid, {
className: dist_clsx('block-editor-list-view-tree', {
'is-dragging': draggedClientIds?.length > 0 && blockDropTargetIndex !== undefined
"aria-label": (0,external_wp_i18n_namespaceObject.__)('Block navigation structure'),
onCollapseRow: collapseRow,
applicationAriaLabel: (0,external_wp_i18n_namespaceObject.__)('Block navigation structure'),
"aria-describedby": describedById,
'--wp-admin--list-view-dragged-items-height': draggedClientIds?.length ? `${BLOCK_LIST_ITEM_HEIGHT * (draggedClientIds.length - 1)}px` : null
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ListViewContext.Provider, {
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(branch, {
selectBlock: selectEditorBlock,
showBlockMovers: showBlockMovers,
fixedListWindow: fixedListWindow,
selectedClientIds: selectedClientIds,
shouldShowInnerBlocks: shouldShowInnerBlocks,
showAppender: showAppender
// This is the private API for the ListView component.
// It allows access to all props, not just the public ones.
const PrivateListView = (0,external_wp_element_namespaceObject.forwardRef)(ListViewComponent);
// This is the public API for the ListView component.
// We wrap the PrivateListView component to hide some props from the public API.
/* harmony default export */ const components_list_view = ((0,external_wp_element_namespaceObject.forwardRef)((props, ref) => {
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PrivateListView, {
additionalBlockContent: null,
blockSettingsMenu: undefined
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-navigation/dropdown.js