Skip to content

Commit

Permalink
DRY up the two places we show a list of content blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
noisysocks committed Apr 24, 2023
1 parent 62249b7 commit 6cc9603
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 150 deletions.
117 changes: 15 additions & 102 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,112 +29,34 @@ 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( () => {
if ( ! block ) {
return [];
}
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 ContentBlocksList from '../content-blocks-list';

function BlockInspectorLockedBlocks( { contentLockingBlockClientId } ) {
const { blockTypes, contentLockingBlock, selectedBlock } = useSelect(
( select ) => {
return {
blockTypes: select( blocksStore ).getBlockTypes(),
contentLockingBlock: select( blockEditorStore ).getBlock(
contentLockingBlockClientId
),
selectedBlock: select( blockEditorStore ).getSelectedBlock(),
};
},
[ contentLockingBlockClientId ]
const selectedBlockClientId = useSelect(
( select ) => select( blockEditorStore ).getSelectedBlockClientId(),
[]
);
const blockInformation = useBlockDisplayInformation(
contentLockingBlock?.clientId ?? selectedBlock.clientId
contentLockingBlockClientId ?? selectedBlockClientId
);
const contentBlocks = useContentBlocks( blockTypes, contentLockingBlock );
return (
<div className="block-editor-block-inspector">
<BlockCard
{ ...blockInformation }
className={ blockInformation.isSynced && 'is-synced' }
/>
{ contentLockingBlock && (
{ contentLockingBlockClientId && (
<BlockVariationTransforms
blockClientId={ contentLockingBlock }
blockClientId={ contentLockingBlockClientId }
/>
) }
<BlockInfo.Slot />
{ !! contentBlocks.length && (
<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>
{ contentLockingBlockClientId && (
<PanelBody title={ __( 'Content' ) }>
<ContentBlocksList
rootClientId={ contentLockingBlockClientId }
/>
</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;
}
69 changes: 69 additions & 0 deletions packages/block-editor/src/components/content-blocks-list/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import {
Button,
__experimentalVStack as VStack,
__experimentalHStack as HStack,
FlexItem,
} from '@wordpress/components';
import { getBlockType } from '@wordpress/blocks';

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

export default function ContentBlocksList( { rootClientId } ) {
const { contentBlocks, selectedBlockClientId } = useSelect(
( select ) => {
const {
__experimentalGetContentClientIdsTree,
getBlockName,
getSelectedBlockClientId,
} = select( blockEditorStore );
return {
contentBlocks: __experimentalGetContentClientIdsTree(
rootClientId
)
.map( ( block ) => ( {
...block,
blockName: getBlockName( block.clientId ),
} ) )
.filter(
( { blockName } ) => blockName !== 'core/list-item'
),
selectedBlockClientId: getSelectedBlockClientId(),
};
},
[ rootClientId ]
);

const { selectBlock } = useDispatch( blockEditorStore );

if ( ! contentBlocks.length ) {
return null;
}

return (
<VStack spacing={ 1 }>
{ contentBlocks.map( ( { clientId, blockName } ) => {
const blockType = getBlockType( blockName );
return (
<Button
key={ clientId }
isPressed={ clientId === selectedBlockClientId }
onClick={ () => selectBlock( clientId ) }
>
<HStack justify="flex-start">
<BlockIcon icon={ blockType.icon } />
<FlexItem>{ blockType.title }</FlexItem>
</HStack>
</Button>
);
} ) }
</VStack>
);
}
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export {
isValueSpacingPreset,
getCustomValueFromPreset,
} from './spacing-sizes-control/utils';
export { default as __experimentalContentBlocksList } from './content-blocks-list';
/*
* Content Related Components
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ import { humanTimeDiff } from '@wordpress/date';
import { useSelect, useDispatch } from '@wordpress/data';
import { useEntityRecord } from '@wordpress/core-data';
import {
store as blockEditorStore,
BlockIcon,
BlockContextProvider,
BlockPreview,
__experimentalContentBlocksList as ContentBlocksList,
} from '@wordpress/block-editor';
import { getBlockType } from '@wordpress/blocks';
import { useMemo } from '@wordpress/element';

/**
Expand All @@ -29,29 +27,8 @@ import removePageFromBlockContext from '../../../utils/remove-page-from-block-co
import SidebarCard from '../sidebar-card';

export default function PagePanels() {
const { context, contentBlocks, selectedBlockClientId } = useSelect(
( select ) => {
const { getEditedPostContext } = select( editSiteStore );
const {
getSettings,
getClientIdsWithDescendants,
getBlockName,
getSelectedBlockClientId,
} = select( blockEditorStore );
const { contentBlockTypes } = getSettings();
return {
context: getEditedPostContext(),
contentBlocks: getClientIdsWithDescendants()
.map( ( clientId ) => ( {
clientId,
blockName: getBlockName( clientId ),
} ) )
.filter( ( { blockName } ) =>
contentBlockTypes.includes( blockName )
),
selectedBlockClientId: getSelectedBlockClientId(),
};
},
const context = useSelect(
( select ) => select( editSiteStore ).getEditedPostContext(),
[]
);

Expand All @@ -64,7 +41,6 @@ export default function PagePanels() {
record: template,
} = useEditedEntityRecord();

const { selectBlock } = useDispatch( blockEditorStore );
const { togglePageContentLock } = useDispatch( editSiteStore );

const blockContext = useMemo(
Expand All @@ -89,23 +65,8 @@ export default function PagePanels() {
) }
/>
</PanelBody>
{ /* TODO: DRY this with BlockInspectorLockedBlocks. */ }
<PanelBody title={ __( 'Content' ) }>
<VStack>
{ contentBlocks.map( ( { clientId, blockName } ) => {
const blockType = getBlockType( blockName );
return (
<Button
key={ clientId }
icon={ <BlockIcon icon={ blockType.icon } /> }
isPressed={ clientId === selectedBlockClientId }
onClick={ () => selectBlock( clientId ) }
>
{ blockType.title }
</Button>
);
} ) }
</VStack>
<ContentBlocksList />
</PanelBody>
<PanelBody
className="edit-site-edit-template-panel"
Expand Down

0 comments on commit 6cc9603

Please sign in to comment.