: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
title: reusableBlock.title?.raw,
content: reusableBlock.content?.raw,
syncStatus: reusableBlock.wp_pattern_sync_status
const syncedPatternInserterItems = canInsertBlockTypeUnmemoized(state, 'core/block', rootClientId) ? unlock(select(STORE_NAME)).getReusableBlocks().map(buildReusableBlockInserterItem) : [];
const buildBlockTypeInserterItem = buildBlockTypeItem(state, {
let blockTypeInserterItems = (0,external_wp_blocks_namespaceObject.getBlockTypes)().filter(blockType => (0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockType, 'inserter', true)).map(buildBlockTypeInserterItem);
if (options[withRootClientIdOptionKey]) {
blockTypeInserterItems = blockTypeInserterItems.reduce((accumulator, item) => {
item.rootClientId = rootClientId !== null && rootClientId !== void 0 ? rootClientId : '';
while (!canInsertBlockTypeUnmemoized(state, item.name, item.rootClientId)) {
if (!item.rootClientId) {
sectionRootClientId = unlock(getSettings(state)).sectionRootClientId;
if (sectionRootClientId && canInsertBlockTypeUnmemoized(state, item.name, sectionRootClientId)) {
item.rootClientId = sectionRootClientId;
delete item.rootClientId;
const parentClientId = getBlockRootClientId(state, item.rootClientId);
item.rootClientId = parentClientId;
// We could also add non insertable items and gray them out.
if (item.hasOwnProperty('rootClientId')) {
blockTypeInserterItems = blockTypeInserterItems.filter(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId));
const items = blockTypeInserterItems.reduce((accumulator, item) => {
// Exclude any block type item that is to be replaced by a default variation.
const variationMapper = getItemFromVariation(state, item);
accumulator.push(...variations.map(variationMapper));
// Ensure core blocks are prioritized in the returned results,
// because third party blocks can be registered earlier than
// the core blocks (usually by using the `init` action),
// thus affecting the display order.
// We don't sort reusable blocks as they are handled differently.
const groupByType = (blocks, block) => {
const type = block.name.startsWith('core/') ? core : noncore;
} = items.reduce(groupByType, {
const sortedBlockTypes = [...coreItems, ...nonCoreItems];
return [...sortedBlockTypes, ...syncedPatternInserterItems];
}, (state, rootClientId) => [(0,external_wp_blocks_namespaceObject.getBlockTypes)(), unlock(select(STORE_NAME)).getReusableBlocks(), state.blocks.order, state.preferences.insertUsage, ...getInsertBlockTypeDependants(state, rootClientId)]));
* Determines the items that appear in the available block transforms list.
* Each item object contains what's necessary to display a menu item in the
* transform list and handle its selection.
* The 'frecency' property is a heuristic (https://en.wikipedia.org/wiki/Frecency)
* that combines block usage frequenty and recency.
* Items are returned ordered descendingly by their 'frecency'.
* @param {Object} state Editor state.
* @param {Object|Object[]} blocks Block object or array objects.
* @param {?string} rootClientId Optional root client ID of block list.
* @return {WPEditorTransformItem[]} Items that appear in inserter.
* @typedef {Object} WPEditorTransformItem
* @property {string} id Unique identifier for the item.
* @property {string} name The type of block to create.
* @property {string} title Title of the item, as it appears in the inserter.
* @property {string} icon Dashicon for the item, as it appears in the inserter.
* @property {boolean} isDisabled Whether or not the user should be prevented from inserting
* @property {number} frecency Heuristic that combines frequency and recency.
const getBlockTransformItems = (0,external_wp_data_namespaceObject.createSelector)((state, blocks, rootClientId = null) => {
const normalizedBlocks = Array.isArray(blocks) ? blocks : [blocks];
const buildBlockTypeTransformItem = buildBlockTypeItem(state, {
const blockTypeTransformItems = (0,external_wp_blocks_namespaceObject.getBlockTypes)().filter(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId)).map(buildBlockTypeTransformItem);
const itemsByName = Object.fromEntries(Object.entries(blockTypeTransformItems).map(([, value]) => [value.name, value]));
const possibleTransforms = (0,external_wp_blocks_namespaceObject.getPossibleBlockTransformations)(normalizedBlocks).reduce((accumulator, block) => {
if (itemsByName[block?.name]) {
accumulator.push(itemsByName[block.name]);
return orderBy(possibleTransforms, block => itemsByName[block.name].frecency, 'desc');
}, (state, blocks, rootClientId) => [(0,external_wp_blocks_namespaceObject.getBlockTypes)(), state.preferences.insertUsage, ...getInsertBlockTypeDependants(state, rootClientId)]);
* Determines whether there are items to show in the inserter.
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
* @return {boolean} Items that appear in inserter.
const hasInserterItems = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, rootClientId = null) => {
const hasBlockType = (0,external_wp_blocks_namespaceObject.getBlockTypes)().some(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId));
const hasReusableBlock = canInsertBlockTypeUnmemoized(state, 'core/block', rootClientId) && unlock(select(STORE_NAME)).getReusableBlocks().length > 0;
* Returns the list of allowed inserter blocks for inner blocks children.
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
* @return {Array?} The list of allowed block types.
const getAllowedBlocks = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null) => {
const blockTypes = (0,external_wp_blocks_namespaceObject.getBlockTypes)().filter(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId));
const hasReusableBlock = canInsertBlockTypeUnmemoized(state, 'core/block', rootClientId) && unlock(select(STORE_NAME)).getReusableBlocks().length > 0;
blockTypes.push('core/block');
}, (state, rootClientId) => [(0,external_wp_blocks_namespaceObject.getBlockTypes)(), unlock(select(STORE_NAME)).getReusableBlocks(), ...getInsertBlockTypeDependants(state, rootClientId)]));
const __experimentalGetAllowedBlocks = (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null) => {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).__experimentalGetAllowedBlocks', {
alternative: 'wp.data.select( "core/block-editor" ).getAllowedBlocks',
return getAllowedBlocks(state, rootClientId);
}, (state, rootClientId) => getAllowedBlocks.getDependants(state, rootClientId));
* Returns the block to be directly inserted by the block appender.
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
* @return {WPDirectInsertBlock|undefined} The block type to be directly inserted.
* @typedef {Object} WPDirectInsertBlock
* @property {string} name The type of block.
* @property {?Object} attributes Attributes to pass to the newly created block.
* @property {?Array<string>} attributesToCopy Attributes to be copied from adjecent blocks when inserted.
function getDirectInsertBlock(state, rootClientId = null) {
var _state$blockListSetti;
} = (_state$blockListSetti = state.blockListSettings[rootClientId]) !== null && _state$blockListSetti !== void 0 ? _state$blockListSetti : {};
if (!defaultBlock || !directInsert) {
function __experimentalGetDirectInsertBlock(state, rootClientId = null) {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).__experimentalGetDirectInsertBlock', {
alternative: 'wp.data.select( "core/block-editor" ).getDirectInsertBlock',
return getDirectInsertBlock(state, rootClientId);
const __experimentalGetParsedPattern = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, patternName) => {
const pattern = unlock(select(STORE_NAME)).getPatternBySlug(patternName);
return pattern ? getParsedPattern(pattern) : null;
const getAllowedPatternsDependants = select => (state, rootClientId) => [...getAllPatternsDependants(select)(state), ...getInsertBlockTypeDependants(state, rootClientId)];
* Returns the list of allowed patterns for inner blocks children.
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional target root client ID.
* @return {Array?} The list of allowed patterns.
const __experimentalGetAllowedPatterns = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => {
return (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null) => {
} = unlock(select(STORE_NAME));
const patterns = getAllPatterns();
const parsedPatterns = patterns.filter(({
}) => !!inserter).map(getParsedPattern);
const availableParsedPatterns = parsedPatterns.filter(({
}) => checkAllowListRecursive(blocks, allowedBlockTypes));
const patternsAllowed = availableParsedPatterns.filter(({
}) => canInsertBlockType(state, name, rootClientId)));
}, getAllowedPatternsDependants(select));
* Returns the list of patterns based on their declared `blockTypes`
* Patterns can use `blockTypes` to integrate in work flows like
* suggesting appropriate patterns in a Placeholder state(during insertion)
* or blocks transformations.
* @param {Object} state Editor state.
* @param {string|string[]} blockNames Block's name or array of block names to find matching pattens.
* @param {?string} rootClientId Optional target root client ID.
* @return {Array} The list of matched block patterns based on declared `blockTypes` and block name.
const getPatternsByBlockTypes = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, blockNames, rootClientId = null) => {
return selectors_EMPTY_ARRAY;
const patterns = select(STORE_NAME).__experimentalGetAllowedPatterns(rootClientId);
const normalizedBlockNames = Array.isArray(blockNames) ? blockNames : [blockNames];
const filteredPatterns = patterns.filter(pattern => pattern?.blockTypes?.some?.(blockName => normalizedBlockNames.includes(blockName)));
if (filteredPatterns.length === 0) {
return selectors_EMPTY_ARRAY;
}, (state, blockNames, rootClientId) => getAllowedPatternsDependants(select)(state, rootClientId)));
const __experimentalGetPatternsByBlockTypes = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).__experimentalGetPatternsByBlockTypes', {
alternative: 'wp.data.select( "core/block-editor" ).getPatternsByBlockTypes',
return select(STORE_NAME).getPatternsByBlockTypes;
* Determines the items that appear in the available pattern transforms list.
* For now we only handle blocks without InnerBlocks and take into account
* the `__experimentalRole` property of blocks' attributes for the transformation.
* We return the first set of possible eligible block patterns,
* by checking the `blockTypes` property. We still have to recurse through
* block pattern's blocks and try to find matches from the selected blocks.
* Now this happens in the consumer to avoid heavy operations in the selector.
* @param {Object} state Editor state.
* @param {Object[]} blocks The selected blocks.
* @param {?string} rootClientId Optional root client ID of block list.
* @return {WPBlockPattern[]} Items that are eligible for a pattern transformation.
const __experimentalGetPatternTransformItems = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, blocks, rootClientId = null) => {
return selectors_EMPTY_ARRAY;
* For now we only handle blocks without InnerBlocks and take into account
* the `__experimentalRole` property of blocks' attributes for the transformation.
* Note that the blocks have been retrieved through `getBlock`, which doesn't
* return the inner blocks of an inner block controller, so we still need
* to check for this case too.
}) => innerBlocks.length || areInnerBlocksControlled(state, clientId))) {
return selectors_EMPTY_ARRAY;
// Create a Set of the selected block names that is used in patterns filtering.
const selectedBlockNames = Array.from(new Set(blocks.map(({
* Here we will return first set of possible eligible block patterns,
* by checking the `blockTypes` property. We still have to recurse through
* block pattern's blocks and try to find matches from the selected blocks.
* Now this happens in the consumer to avoid heavy operations in the selector.
return select(STORE_NAME).getPatternsByBlockTypes(selectedBlockNames, rootClientId);
}, (state, blocks, rootClientId) => getAllowedPatternsDependants(select)(state, rootClientId)));
* Returns the Block List settings of a block, if any exist.
* @param {Object} state Editor state.
* @param {?string} clientId Block client ID.
* @return {?Object} Block settings of the block if set.
function getBlockListSettings(state, clientId) {
return state.blockListSettings[clientId];
* Returns the editor settings.
* @param {Object} state Editor state.
* @return {Object} The editor settings object.
function getSettings(state) {
* Returns true if the most recent block change is be considered persistent, or
* false otherwise. A persistent change is one committed by BlockEditorProvider
* via its `onChange` callback, in addition to `onInput`.
* @param {Object} state Block editor state.
* @return {boolean} Whether the most recent block change was persistent.
function isLastBlockChangePersistent(state) {
return state.blocks.isPersistentChange;
* Returns the block list settings for an array of blocks, if any exist.
* @param {Object} state Editor state.
* @param {Array} clientIds Block client IDs.
* @return {Object} An object where the keys are client ids and the values are
* a block list setting object.
const __experimentalGetBlockListSettingsForBlocks = (0,external_wp_data_namespaceObject.createSelector)((state, clientIds = []) => {
return clientIds.reduce((blockListSettingsForBlocks, clientId) => {
if (!state.blockListSettings[clientId]) {
return blockListSettingsForBlocks;
...blockListSettingsForBlocks,
[clientId]: state.blockListSettings[clientId]
}, state => [state.blockListSettings]);
* Returns the title of a given reusable block
* @param {Object} state Global application state.
* @param {number|string} ref The shared block's ID.
* @return {string} The reusable block saved title.
const __experimentalGetReusableBlockTitle = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, ref) => {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__experimentalGetReusableBlockTitle", {
const reusableBlock = unlock(select(STORE_NAME)).getReusableBlocks().find(block => block.id === ref);
return reusableBlock.title?.raw;
}, () => [unlock(select(STORE_NAME)).getReusableBlocks()]));
* Returns true if the most recent block change is be considered ignored, or
* false otherwise. An ignored change is one not to be committed by
* BlockEditorProvider, neither via `onChange` nor `onInput`.
* @param {Object} state Block editor state.
* @return {boolean} Whether the most recent block change was ignored.
function __unstableIsLastBlockChangeIgnored(state) {
// TODO: Removal Plan: Changes incurred by RECEIVE_BLOCKS should not be
// ignored if in-fact they result in a change in blocks state. The current
// need to ignore changes not a result of user interaction should be
// accounted for in the refactoring of reusable blocks as occurring within
// their own separate block editor / state (#7119).
return state.blocks.isIgnoredChange;
* Returns the block attributes changed as a result of the last dispatched
* @param {Object} state Block editor state.
* @return {Object<string,Object>} Subsets of block attributes changed, keyed
function __experimentalGetLastBlockAttributeChanges(state) {
return state.lastBlockAttributesChange;
* Returns whether the navigation mode is enabled.
* @param {Object} state Editor state.
* @return {boolean} Is navigation mode enabled.
function isNavigationMode(state) {
return state.editorMode === 'navigation';
* Returns the current editor mode.
* @param {Object} state Editor state.
* @return {string} the editor mode.
function __unstableGetEditorMode(state) {
* Returns whether block moving mode is enabled.
* @param {Object} state Editor state.
* @return {string} Client Id of moving block.
function selectors_hasBlockMovingClientId(state) {
return state.hasBlockMovingClientId;
* Returns true if the last change was an automatic change, false otherwise.
* @param {Object} state Global application state.
* @return {boolean} Whether the last change was automatic.
function didAutomaticChange(state) {
return !!state.automaticChangeStatus;
* Returns true if the current highlighted block matches the block clientId.
* @param {Object} state Global application state.
* @param {string} clientId The block to check.
* @return {boolean} Whether the block is currently highlighted.
function isBlockHighlighted(state, clientId) {
return state.highlightedBlock === clientId;
* Checks if a given block has controlled inner blocks.