Skip to content

Commit

Permalink
DRY up ContentBlocksList and BlockInspectorLockedBlocks (WordPress#51281
Browse files Browse the repository at this point in the history
)

* DRY up ContentBlocksList and BlockInspectorLockedBlocks

Extract BlockQuickNavigation out of ContentBlocksList and
BlockInspectorLockedBlocks so that we're not repeating the same code
that outputs a list of block navigation links.

* Add back check that ensures list items don't appear in list

* Remove unnecessary CSS

* Reduce amount of rerendering

* Update __experimentalGetGlobalBlocksByName
  • Loading branch information
noisysocks authored and sethrubenstein committed Jul 13, 2023
1 parent a675dae commit a5ab874
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 177 deletions.
110 changes: 18 additions & 92 deletions packages/block-editor/src/components/block-inspector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,8 @@ import {
hasBlockSupport,
store as blocksStore,
} from '@wordpress/blocks';
import {
FlexItem,
PanelBody,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
Button,
__unstableMotion as motion,
} from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { useMemo, useCallback } from '@wordpress/element';
import { PanelBody, __unstableMotion as motion } from '@wordpress/components';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
Expand All @@ -28,7 +20,6 @@ import MultiSelectionInspector from '../multi-selection-inspector';
import BlockVariationTransforms from '../block-variation-transforms';
import useBlockDisplayInformation from '../use-block-display-information';
import { store as blockEditorStore } from '../../store';
import BlockIcon from '../block-icon';
import BlockStyles from '../block-styles';
import DefaultStylePicker from '../default-style-picker';
import { default as InspectorControls } from '../inspector-controls';
Expand All @@ -38,77 +29,26 @@ import AdvancedControls from '../inspector-controls-tabs/advanced-controls-panel
import PositionControls from '../inspector-controls-tabs/position-controls-panel';
import useBlockInspectorAnimationSettings from './useBlockInspectorAnimationSettings';
import BlockInfo from '../block-info-slot-fill';

function useContentBlocks( blockTypes, block ) {
const contentBlocksObjectAux = useMemo( () => {
return blockTypes.reduce( ( result, blockType ) => {
if (
blockType.name !== 'core/list-item' &&
Object.entries( blockType.attributes ).some(
( [ , { __experimentalRole } ] ) =>
__experimentalRole === 'content'
)
) {
result[ blockType.name ] = true;
}
return result;
}, {} );
}, [ blockTypes ] );
const isContentBlock = useCallback(
( blockName ) => {
return !! contentBlocksObjectAux[ blockName ];
},
[ contentBlocksObjectAux ]
);
return useMemo( () => {
return getContentBlocks( [ block ], isContentBlock );
}, [ block, isContentBlock ] );
}

function getContentBlocks( blocks, isContentBlock ) {
const result = [];
for ( const block of blocks ) {
if ( isContentBlock( block.name ) ) {
result.push( block );
}
result.push( ...getContentBlocks( block.innerBlocks, isContentBlock ) );
}
return result;
}

function BlockNavigationButton( { blockTypes, block, selectedBlock } ) {
const { selectBlock } = useDispatch( blockEditorStore );
const blockType = blockTypes.find( ( { name } ) => name === block.name );
const isSelected =
selectedBlock && selectedBlock.clientId === block.clientId;
return (
<Button
isPressed={ isSelected }
onClick={ () => selectBlock( block.clientId ) }
>
<HStack justify="flex-start">
<BlockIcon icon={ blockType.icon } />
<FlexItem>{ blockType.title }</FlexItem>
</HStack>
</Button>
);
}
import BlockQuickNavigation from '../block-quick-navigation';
import { unlock } from '../../lock-unlock';

function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) {
const { blockTypes, block, selectedBlock } = useSelect(
const contentClientIds = useSelect(
( select ) => {
return {
blockTypes: select( blocksStore ).getBlockTypes(),
block: select( blockEditorStore ).getBlock(
topLevelLockedBlock
),
selectedBlock: select( blockEditorStore ).getSelectedBlock(),
};
const {
getClientIdsOfDescendants,
getBlockName,
getBlockEditingMode,
} = unlock( select( blockEditorStore ) );
return getClientIdsOfDescendants( [ topLevelLockedBlock ] ).filter(
( clientId ) =>
getBlockName( clientId ) !== 'core/list-item' &&
getBlockEditingMode( clientId ) === 'contentOnly'
);
},
[ topLevelLockedBlock ]
);
const blockInformation = useBlockDisplayInformation( topLevelLockedBlock );
const contentBlocks = useContentBlocks( blockTypes, block );
return (
<div className="block-editor-block-inspector">
<BlockCard
Expand All @@ -117,23 +57,9 @@ function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) {
/>
<BlockVariationTransforms blockClientId={ topLevelLockedBlock } />
<BlockInfo.Slot />
<VStack
spacing={ 1 }
padding={ 4 }
className="block-editor-block-inspector__block-buttons-container"
>
<h2 className="block-editor-block-card__title">
{ __( 'Content' ) }
</h2>
{ contentBlocks.map( ( contentBlock ) => (
<BlockNavigationButton
selectedBlock={ selectedBlock }
key={ contentBlock.clientId }
block={ contentBlock }
blockTypes={ blockTypes }
/>
) ) }
</VStack>
<PanelBody title={ __( 'Content' ) }>
<BlockQuickNavigation clientIds={ contentClientIds } />
</PanelBody>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,3 @@
.block-editor-block-inspector__tab-item {
flex: 1 1 0px;
}

.block-editor-block-inspector__block-buttons-container {
border-top: $border-width solid $gray-200;
padding: $grid-unit-20;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import {
Button,
__experimentalVStack as VStack,
__experimentalHStack as HStack,
FlexItem,
} from '@wordpress/components';
import { getBlockType, __experimentalGetBlockLabel } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import BlockIcon from '../block-icon';

export default function BlockQuickNavigation( { clientIds } ) {
if ( ! clientIds.length ) {
return null;
}
return (
<VStack spacing={ 1 }>
{ clientIds.map( ( clientId ) => (
<BlockQuickNavigationItem
key={ clientId }
clientId={ clientId }
/>
) ) }
</VStack>
);
}

function BlockQuickNavigationItem( { clientId } ) {
const { name, attributes, isSelected } = useSelect(
( select ) => {
const {
getBlockName,
getBlockAttributes,
isBlockSelected,
hasSelectedInnerBlock,
} = select( blockEditorStore );
return {
name: getBlockName( clientId ),
attributes: getBlockAttributes( clientId ),
isSelected:
isBlockSelected( clientId ) ||
hasSelectedInnerBlock( clientId, /* deep: */ true ),
};
},
[ clientId ]
);
const { selectBlock } = useDispatch( blockEditorStore );
const blockType = getBlockType( name );
return (
<Button
key={ clientId }
isPressed={ isSelected }
onClick={ () => selectBlock( clientId ) }
>
<HStack justify="flex-start">
<BlockIcon icon={ blockType.icon } />
<FlexItem>
{ __experimentalGetBlockLabel(
blockType,
attributes,
'list-view'
) }
</FlexItem>
</HStack>
</Button>
);
}
2 changes: 2 additions & 0 deletions packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import BlockInfo from './components/block-info-slot-fill';
import { useShouldContextualToolbarShow } from './utils/use-should-contextual-toolbar-show';
import { cleanEmptyObject } from './hooks/utils';
import { useBlockEditingMode } from './components/block-editing-mode';
import BlockQuickNavigation from './components/block-quick-navigation';

/**
* Private @wordpress/block-editor APIs.
Expand All @@ -26,4 +27,5 @@ lock( privateApis, {
useShouldContextualToolbarShow,
cleanEmptyObject,
useBlockEditingMode,
BlockQuickNavigation,
} );
5 changes: 4 additions & 1 deletion packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,13 @@ export const __experimentalGetGlobalBlocksByName = createSelector(
if ( ! blockName ) {
return EMPTY_ARRAY;
}
const blockNames = Array.isArray( blockName )
? blockName
: [ blockName ];
const clientIds = getClientIdsWithDescendants( state );
const foundBlocks = clientIds.filter( ( clientId ) => {
const block = state.blocks.byClientId.get( clientId );
return block.name === blockName;
return blockNames.includes( block.name );
} );
return foundBlocks.length > 0 ? foundBlocks : EMPTY_ARRAY;
},
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useMemo } from '@wordpress/element';
import { store as editSiteStore } from '../../../store';
import useEditedEntityRecord from '../../use-edited-entity-record';
import SidebarCard from '../sidebar-card';
import ContentBlocksList from './content-blocks-list';
import PageContent from './page-content';

export default function PagePanels() {
const context = useSelect(
Expand Down Expand Up @@ -62,7 +62,7 @@ export default function PagePanels() {
/>
</PanelBody>
<PanelBody title={ __( 'Content' ) }>
<ContentBlocksList />
<PageContent />
</PanelBody>
<PanelBody title={ __( 'Template' ) }>
<VStack>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import {
store as blockEditorStore,
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { PAGE_CONTENT_BLOCK_TYPES } from '../../page-content-focus/constants';
import { unlock } from '../../../private-apis';

const { BlockQuickNavigation } = unlock( blockEditorPrivateApis );

export default function PageContent() {
const clientIds = useSelect(
( select ) =>
select( blockEditorStore ).__experimentalGetGlobalBlocksByName(
PAGE_CONTENT_BLOCK_TYPES
),
[]
);
return <BlockQuickNavigation clientIds={ clientIds } />;
}

0 comments on commit a5ab874

Please sign in to comment.