diff --git a/package-lock.json b/package-lock.json index c121d2acac43..97b6f1d68fb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19160,6 +19160,7 @@ "@wordpress/notices": "file:packages/notices", "@wordpress/plugins": "file:packages/plugins", "@wordpress/primitives": "file:packages/primitives", + "@wordpress/reusable-blocks": "file:packages/reusable-blocks", "@wordpress/url": "file:packages/url", "classnames": "^2.3.1", "downloadjs": "^1.4.7", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 55078e23e126..44f8926e7695 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -50,6 +50,7 @@ "@wordpress/notices": "file:../notices", "@wordpress/plugins": "file:../plugins", "@wordpress/primitives": "file:../primitives", + "@wordpress/reusable-blocks": "file:../reusable-blocks", "@wordpress/url": "file:../url", "classnames": "^2.3.1", "downloadjs": "^1.4.7", diff --git a/packages/edit-site/src/components/block-editor/index.js b/packages/edit-site/src/components/block-editor/index.js index 6b3f1b5ce24d..90c68da8c39f 100644 --- a/packages/edit-site/src/components/block-editor/index.js +++ b/packages/edit-site/src/components/block-editor/index.js @@ -20,6 +20,7 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { useMergeRefs, useViewportMatch } from '@wordpress/compose'; +import { ReusableBlocksMenuItems } from '@wordpress/reusable-blocks'; /** * Internal dependencies @@ -132,6 +133,7 @@ export default function BlockEditor( { setIsInserterOpen } ) { ) } + ); } diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index c93f4a2f945f..4eb26e33ee12 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -11,6 +11,7 @@ import { store as coreDataStore } from '@wordpress/core-data'; import { createRegistrySelector } from '@wordpress/data'; import { uploadMedia } from '@wordpress/media-utils'; import { isTemplatePart } from '@wordpress/blocks'; +import { Platform } from '@wordpress/element'; /** * Internal dependencies @@ -64,6 +65,22 @@ export const getCanUserCreateMedia = createRegistrySelector( ( select ) => () => select( coreDataStore ).canUser( 'create', 'media' ) ); +/** + * Returns any available Reusable blocks. + * + * @param {Object} state Global application state. + * + * @return {Array} The available reusable blocks. + */ +export const getReusableBlocks = createRegistrySelector( ( select ) => () => { + const isWeb = Platform.OS === 'web'; + return isWeb + ? select( coreDataStore ).getEntityRecords( 'postType', 'wp_block', { + per_page: -1, + } ) + : []; +} ); + /** * Returns the settings, taking into account active features and permissions. * @@ -80,6 +97,7 @@ export const getSettings = createSelector( focusMode: isFeatureActive( state, 'focusMode' ), hasFixedToolbar: isFeatureActive( state, 'fixedToolbar' ), __experimentalSetIsInserterOpened: setIsInserterOpen, + __experimentalReusableBlocks: getReusableBlocks( state ), }; const canUserCreateMedia = getCanUserCreateMedia( state ); @@ -101,6 +119,7 @@ export const getSettings = createSelector( state.settings, isFeatureActive( state, 'focusMode' ), isFeatureActive( state, 'fixedToolbar' ), + getReusableBlocks( state ), ] ); diff --git a/packages/edit-site/src/store/test/selectors.js b/packages/edit-site/src/store/test/selectors.js index d98a07365f1d..d1d90b7ea642 100644 --- a/packages/edit-site/src/store/test/selectors.js +++ b/packages/edit-site/src/store/test/selectors.js @@ -17,6 +17,7 @@ import { getPreviousEditedPostId, getPage, getNavigationPanelActiveMenu, + getReusableBlocks, isNavigationOpened, isInserterOpened, isListViewOpened, @@ -24,9 +25,13 @@ import { describe( 'selectors', () => { const canUser = jest.fn( () => true ); + const getEntityRecords = jest.fn( () => [] ); getCanUserCreateMedia.registry = { select: jest.fn( () => ( { canUser } ) ), }; + getReusableBlocks.registry = { + select: jest.fn( () => ( { getEntityRecords } ) ), + }; describe( 'isFeatureActive', () => { it( 'is tolerant to an undefined features preference', () => { @@ -83,6 +88,22 @@ describe( 'selectors', () => { } ); } ); + describe( 'getReusableBlocks', () => { + it( "selects `getEntityRecords( 'postType', 'wp_block' )` from the core store", () => { + expect( getReusableBlocks() ).toEqual( [] ); + expect( getReusableBlocks.registry.select ).toHaveBeenCalledWith( + coreDataStore + ); + expect( getEntityRecords ).toHaveBeenCalledWith( + 'postType', + 'wp_block', + { + per_page: -1, + } + ); + } ); + } ); + describe( 'getSettings', () => { it( "returns the settings when the user can't create media", () => { canUser.mockReturnValueOnce( false ); @@ -94,6 +115,7 @@ describe( 'selectors', () => { focusMode: false, hasFixedToolbar: false, __experimentalSetIsInserterOpened: setInserterOpened, + __experimentalReusableBlocks: [], } ); } ); @@ -108,12 +130,14 @@ describe( 'selectors', () => { }, }; const setInserterOpened = () => {}; + expect( getSettings( state, setInserterOpened ) ).toEqual( { outlineMode: true, key: 'value', focusMode: true, hasFixedToolbar: true, __experimentalSetIsInserterOpened: setInserterOpened, + __experimentalReusableBlocks: [], mediaUpload: expect.any( Function ), } ); } );