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

Always show the block appender when its parent is selected #36656

Merged
merged 7 commits into from Nov 24, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,7 +1,6 @@
/**
* External dependencies
*/
import { last } from 'lodash';
import classnames from 'classnames';

/**
Expand All @@ -18,7 +17,6 @@ import ButtonBlockAppender from '../button-block-appender';
import { store as blockEditorStore } from '../../store';

function BlockListAppender( {
blockClientIds,
rootClientId,
canInsertDefaultBlock,
isLocked,
Expand All @@ -36,30 +34,18 @@ function BlockListAppender( {
// Prefer custom render prop if provided.
appender = <CustomAppender />;
} else {
const isDocumentAppender = ! rootClientId;
const isParentSelected = selectedBlockClientId === rootClientId;
const isAnotherDefaultAppenderAlreadyDisplayed =
selectedBlockClientId &&
! blockClientIds.includes( selectedBlockClientId );
const isParentSelected =
selectedBlockClientId === rootClientId ||
( ! rootClientId && ! selectedBlockClientId );

if (
! isDocumentAppender &&
! isParentSelected &&
( ! selectedBlockClientId ||
isAnotherDefaultAppenderAlreadyDisplayed )
) {
if ( ! isParentSelected ) {
return null;
}

if ( canInsertDefaultBlock ) {
// Render the default block appender when renderAppender has not been
// provided and the context supports use of the default appender.
appender = (
<DefaultBlockAppender
rootClientId={ rootClientId }
lastBlockClientId={ last( blockClientIds ) }
/>
);
appender = <DefaultBlockAppender rootClientId={ rootClientId } />;
} else {
// Fallback in the case no renderAppender has been provided and the
// default block can't be inserted.
Expand Down Expand Up @@ -103,15 +89,13 @@ function BlockListAppender( {

export default withSelect( ( select, { rootClientId } ) => {
const {
getBlockOrder,
canInsertBlockType,
getTemplateLock,
getSelectedBlockClientId,
} = select( blockEditorStore );

return {
isLocked: !! getTemplateLock( rootClientId ),
blockClientIds: getBlockOrder( rootClientId ),
canInsertDefaultBlock: canInsertBlockType(
getDefaultBlockName(),
rootClientId
Expand Down
Expand Up @@ -8,9 +8,9 @@ import classnames from 'classnames';
*/
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { getDefaultBlockName } from '@wordpress/blocks';
import { decodeEntities } from '@wordpress/html-entities';
import { withSelect, withDispatch } from '@wordpress/data';
import { ENTER, SPACE } from '@wordpress/keycodes';

/**
* Internal dependencies
Expand All @@ -26,13 +26,12 @@ export const ZWNBSP = '\ufeff';

export function DefaultBlockAppender( {
isLocked,
isVisible,
onAppend,
showPrompt,
placeholder,
rootClientId,
} ) {
if ( isLocked || ! isVisible ) {
if ( isLocked ) {
return null;
}

Expand All @@ -48,20 +47,23 @@ export function DefaultBlockAppender( {
>
<p
tabIndex="0"
// Only necessary for `useCanvasClickRedirect` to consider it
// as a target. Ideally it should consider any tabbable target,
// but the inserter is rendered in place while it should be
// rendered in a popover, just like it does for an empty
// paragraph block.
contentEditable
suppressContentEditableWarning
// We want this element to be styled as a paragraph by themes.
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
role="button"
aria-label={ __( 'Add block' ) }
aria-label={ __( 'Add default block' ) }
// A wrapping container for this one already has the wp-block className.
className="block-editor-default-block-appender__content"
onFocus={ onAppend }
onKeyDown={ ( event ) => {
if ( ENTER === event.keyCode || SPACE === event.keyCode ) {
onAppend();
}
} }
onClick={ () => onAppend() }
onFocus={ () => {
if ( showPrompt ) {
onAppend();
}
} }
>
{ showPrompt ? value : ZWNBSP }
</p>
Expand All @@ -77,23 +79,14 @@ export function DefaultBlockAppender( {

export default compose(
withSelect( ( select, ownProps ) => {
const {
getBlockCount,
getBlockName,
isBlockValid,
getSettings,
getTemplateLock,
} = select( blockEditorStore );
const { getBlockCount, getSettings, getTemplateLock } = select(
blockEditorStore
);

const isEmpty = ! getBlockCount( ownProps.rootClientId );
const isLastBlockDefault =
getBlockName( ownProps.lastBlockClientId ) ===
getDefaultBlockName();
const isLastBlockValid = isBlockValid( ownProps.lastBlockClientId );
const { bodyPlaceholder } = getSettings();

return {
isVisible: isEmpty || ! isLastBlockDefault || ! isLastBlockValid,
showPrompt: isEmpty,
isLocked: !! getTemplateLock( ownProps.rootClientId ),
placeholder: bodyPlaceholder,
Expand Down
Expand Up @@ -126,3 +126,7 @@
display: flex;
}
}

.block-editor-default-block-appender__content {
cursor: text;
}
Expand Up @@ -6,24 +6,12 @@ exports[`DefaultBlockAppender should append a default block when input focused 1
data-root-client-id=""
>
<p
aria-label="Add block"
aria-label="Add default block"
className="block-editor-default-block-appender__content"
contentEditable={true}
onFocus={
[MockFunction] {
"calls": Array [
Array [],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
}
onClick={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
role="button"
suppressContentEditableWarning={true}
tabIndex="0"
>
Type / to choose a block
Expand All @@ -42,12 +30,12 @@ exports[`DefaultBlockAppender should match snapshot 1`] = `
data-root-client-id=""
>
<p
aria-label="Add block"
aria-label="Add default block"
className="block-editor-default-block-appender__content"
contentEditable={true}
onFocus={[MockFunction]}
onClick={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
role="button"
suppressContentEditableWarning={true}
tabIndex="0"
>
Type / to choose a block
Expand All @@ -66,12 +54,12 @@ exports[`DefaultBlockAppender should optionally show without prompt 1`] = `
data-root-client-id=""
>
<p
aria-label="Add block"
aria-label="Add default block"
className="block-editor-default-block-appender__content"
contentEditable={true}
onFocus={[MockFunction]}
onClick={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
role="button"
suppressContentEditableWarning={true}
tabIndex="0"
>

Expand Down
Expand Up @@ -14,16 +14,10 @@ describe( 'DefaultBlockAppender', () => {
expect( onAppend ).toHaveBeenCalledWith();
};

it( 'should render nothing if not visible', () => {
const wrapper = shallow( <DefaultBlockAppender /> );

expect( wrapper.type() ).toBe( null );
} );

it( 'should match snapshot', () => {
const onAppend = jest.fn();
const wrapper = shallow(
<DefaultBlockAppender isVisible onAppend={ onAppend } showPrompt />
<DefaultBlockAppender onAppend={ onAppend } showPrompt />
);

expect( wrapper ).toMatchSnapshot();
Expand All @@ -32,10 +26,10 @@ describe( 'DefaultBlockAppender', () => {
it( 'should append a default block when input focused', () => {
const onAppend = jest.fn();
const wrapper = shallow(
<DefaultBlockAppender isVisible onAppend={ onAppend } showPrompt />
<DefaultBlockAppender onAppend={ onAppend } showPrompt />
);

wrapper.find( 'p' ).simulate( 'focus' );
wrapper.find( 'p' ).simulate( 'click' );

expect( wrapper ).toMatchSnapshot();

Expand All @@ -45,11 +39,7 @@ describe( 'DefaultBlockAppender', () => {
it( 'should optionally show without prompt', () => {
const onAppend = jest.fn();
const wrapper = shallow(
<DefaultBlockAppender
isVisible
onAppend={ onAppend }
showPrompt={ false }
/>
<DefaultBlockAppender onAppend={ onAppend } showPrompt={ false } />
);
const input = wrapper.find( 'p' );

Expand Down
1 change: 0 additions & 1 deletion packages/block-editor/src/components/index.js
Expand Up @@ -138,7 +138,6 @@ export {
} from './typewriter';
export { default as Warning } from './warning';
export { default as WritingFlow } from './writing-flow';
export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect';
export { default as useBlockDisplayInformation } from './use-block-display-information';
export { default as __unstableIframe } from './iframe';
export { default as __experimentalUseNoRecursiveRenders } from './use-no-recursive-renders';
Expand Down
Expand Up @@ -16,13 +16,8 @@ import BaseDefaultBlockAppender from '../default-block-appender';
import withClientId from './with-client-id';
import { store as blockEditorStore } from '../../store';

export const DefaultBlockAppender = ( { clientId, lastBlockClientId } ) => {
return (
<BaseDefaultBlockAppender
rootClientId={ clientId }
lastBlockClientId={ lastBlockClientId }
/>
);
export const DefaultBlockAppender = ( { clientId } ) => {
return <BaseDefaultBlockAppender rootClientId={ clientId } />;
};

export default compose( [
Expand Down

This file was deleted.

4 changes: 4 additions & 0 deletions packages/e2e-test-utils/src/click-block-appender.js
Expand Up @@ -2,6 +2,10 @@
* Clicks the default block appender.
*/
export async function clickBlockAppender() {
// The block appender is only visible when there's no selection.
await page.evaluate( () =>
window.wp.data.dispatch( 'core/block-editor' ).clearSelectedBlock()
);
const appender = await page.waitForSelector(
'.block-editor-default-block-appender__content'
);
Expand Down
Expand Up @@ -7,6 +7,7 @@ import {
getEditedPostContent,
createNewPost,
insertBlock,
clickBlockAppender,
} from '@wordpress/e2e-test-utils';

describe( 'Preformatted', () => {
Expand Down Expand Up @@ -39,7 +40,7 @@ describe( 'Preformatted', () => {
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '2' );
await page.keyboard.press( 'Enter' );
await page.keyboard.press( 'ArrowDown' );
await clickBlockAppender();
await page.keyboard.type( '3' );
await page.keyboard.press( 'ArrowLeft' );
await page.keyboard.press( 'Backspace' );
Expand Down