Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor: Use hooks instead of HoCs in 'DocumentOutline' #59209

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions packages/editor/src/components/document-outline/check.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
/**
* WordPress dependencies
*/
import { withSelect } from '@wordpress/data';
import { useSelect } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';

function DocumentOutlineCheck( { blocks, children } ) {
const headings = blocks.filter(
( block ) => block.name === 'core/heading'
);
export default function DocumentOutlineCheck( { children } ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check component isn't used anywhere in the codebase, only maintained and exported for backward compatibility.

const hasHeadings = useSelect( ( select ) => {
const { getGlobalBlockCount } = select( blockEditorStore );

if ( headings.length < 1 ) {
return getGlobalBlockCount( 'core/heading' ) > 0;
} );

if ( hasHeadings ) {
Mamaduka marked this conversation as resolved.
Show resolved Hide resolved
return null;
}

return children;
}

export default withSelect( ( select ) => ( {
blocks: select( blockEditorStore ).getBlocks(),
} ) )( DocumentOutlineCheck );
41 changes: 18 additions & 23 deletions packages/editor/src/components/document-outline/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, useDispatch } from '@wordpress/data';
import { useDispatch, useSelect } from '@wordpress/data';
import { create, getTextContent } from '@wordpress/rich-text';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as coreStore } from '@wordpress/core-data';
Expand Down Expand Up @@ -98,15 +97,26 @@ const computeOutlineHeadings = ( blocks = [] ) => {
const isEmptyHeading = ( heading ) =>
! heading.attributes.content || heading.attributes.content.length === 0;

export const DocumentOutline = ( {
blocks = [],
title,
export default function DocumentOutline( {
onSelect,
isTitleSupported,
hasOutlineItemsDisabled,
} ) => {
const headings = computeOutlineHeadings( blocks );
} ) {
const { selectBlock } = useDispatch( blockEditorStore );
const { blocks, title } = useSelect( ( select ) => {
const { getBlocks } = select( blockEditorStore );
const { getEditedPostAttribute } = select( editorStore );
const { getPostType } = select( coreStore );
const postType = getPostType( getEditedPostAttribute( 'type' ) );

return {
title: getEditedPostAttribute( 'title' ),
blocks: getBlocks(),
isTitleSupported: postType?.supports?.title ?? false,
};
} );

const headings = computeOutlineHeadings( blocks );
if ( headings.length < 1 ) {
return (
<div className="editor-document-outline has-no-headings">
Expand Down Expand Up @@ -194,19 +204,4 @@ export const DocumentOutline = ( {
</ul>
</div>
);
};

export default compose(
withSelect( ( select ) => {
const { getBlocks } = select( blockEditorStore );
const { getEditedPostAttribute } = select( editorStore );
const { getPostType } = select( coreStore );
const postType = getPostType( getEditedPostAttribute( 'type' ) );

return {
title: getEditedPostAttribute( 'title' ),
blocks: getBlocks(),
isTitleSupported: postType?.supports?.title ?? false,
};
} )
)( DocumentOutline );
}
33 changes: 26 additions & 7 deletions packages/editor/src/components/document-outline/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,27 @@ import {
registerBlockType,
unregisterBlockType,
} from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { DocumentOutline } from '../';
import DocumentOutline from '../';

jest.mock( '@wordpress/block-editor', () => ( {
BlockTitle: () => 'Block Title',
} ) );
jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() );

function setupMockSelect( blocks ) {
useSelect.mockImplementation( ( mapSelect ) => {
return mapSelect( () => ( {
getBlocks: () => blocks,
getEditedPostAttribute: () => null,
getPostType: () => null,
} ) );
} );
}

describe( 'DocumentOutline', () => {
let paragraph, headingH1, headingH2, headingH3, nestedHeading;
Expand Down Expand Up @@ -77,6 +89,7 @@ describe( 'DocumentOutline', () => {

describe( 'no header blocks present', () => {
it( 'should not render when no blocks provided', () => {
setupMockSelect( [] );
render( <DocumentOutline /> );

expect( screen.queryByRole( 'list' ) ).not.toBeInTheDocument();
Expand All @@ -87,7 +100,8 @@ describe( 'DocumentOutline', () => {
// Set client IDs to a predictable value.
return { ...block, clientId: `clientId_${ index }` };
} );
render( <DocumentOutline blocks={ blocks } /> );
setupMockSelect( blocks );
render( <DocumentOutline /> );

expect( screen.queryByRole( 'list' ) ).not.toBeInTheDocument();
} );
Expand All @@ -99,14 +113,16 @@ describe( 'DocumentOutline', () => {
// Set client IDs to a predictable value.
return { ...block, clientId: `clientId_${ index }` };
} );
render( <DocumentOutline blocks={ blocks } /> );
setupMockSelect( blocks );
render( <DocumentOutline /> );

expect( screen.getByRole( 'list' ) ).toMatchSnapshot();
} );

it( 'should render an item when only one heading provided', () => {
const blocks = [ headingH2 ];
render( <DocumentOutline blocks={ blocks } /> );
setupMockSelect( blocks );
render( <DocumentOutline /> );

const tableOfContentItem = within(
screen.getByRole( 'list' )
Expand All @@ -123,7 +139,8 @@ describe( 'DocumentOutline', () => {
headingH3,
paragraph,
];
render( <DocumentOutline blocks={ blocks } /> );
setupMockSelect( blocks );
render( <DocumentOutline /> );

expect(
within( screen.getByRole( 'list' ) ).getAllByRole( 'listitem' )
Expand All @@ -137,7 +154,8 @@ describe( 'DocumentOutline', () => {
return { ...block, clientId: `clientId_${ index }` };
}
);
render( <DocumentOutline blocks={ blocks } /> );
setupMockSelect( blocks );
render( <DocumentOutline /> );

expect( screen.getByRole( 'list' ) ).toMatchSnapshot();
} );
Expand All @@ -146,7 +164,8 @@ describe( 'DocumentOutline', () => {
describe( 'nested headings', () => {
it( 'should render even if the heading is nested', () => {
const blocks = [ headingH2, nestedHeading ];
render( <DocumentOutline blocks={ blocks } /> );
setupMockSelect( blocks );
render( <DocumentOutline /> );

// Unnested heading and nested heading should appear as items.
const tableOfContentItems = within(
Expand Down
Loading