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

Writing flow: select next block on Enter key #63484

Open
wants to merge 11 commits into
base: trunk
Choose a base branch
from
7 changes: 7 additions & 0 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,11 @@ function BlockListBlockProvider( props ) {
originalBlockClientId: isInvalid
? blocksWithSameName[ 0 ]
: false,
supportsSplitting: hasBlockSupport(
blockName,
'splitting',
false
),
};
},
[ clientId, rootClientId ]
Expand Down Expand Up @@ -743,6 +748,7 @@ function BlockListBlockProvider( props ) {
className,
defaultClassName,
originalBlockClientId,
supportsSplitting,
} = selectedProps;

// Users of the editor.BlockListBlock filter used to be able to
Expand Down Expand Up @@ -791,6 +797,7 @@ function BlockListBlockProvider( props ) {
originalBlockClientId,
themeSupportsLayout,
canMove,
supportsSplitting,
};

// Here we separate between the props passed to BlockListBlock and any other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ export function useFocusFirstElement( { clientId, initialPosition } ) {
return;
}

if ( initialPosition === true ) {
ref.current.focus();
return;
}

// Find all tabbables within node.
const textInputs = focus.tabbable
.find( ref.current )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ export function useEventHandlers( { clientId, isSelected } ) {
return;
}

event.preventDefault();

if ( keyCode === ENTER && isZoomOut() ) {
resetZoomLevel();
} else if ( keyCode === ENTER ) {
insertAfterBlock( clientId );
if ( keyCode === ENTER ) {
if ( isZoomOut() ) {
event.preventDefault();
resetZoomLevel();
}
} else {
event.preventDefault();
removeBlock( clientId );
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,63 @@ import { ENTER } from '@wordpress/keycodes';
import { insert, remove } from '@wordpress/rich-text';

export default ( props ) => ( element ) => {
function onKeyDownDeprecated( event ) {
function onKeyDown( event ) {
if ( event.keyCode !== ENTER ) {
return;
}

const { onReplace, onSplit } = props.current;
const {
onReplace,
onSplit,
supportsSplitting,
disableLineBreaks,
onChange,
value,
onSplitAtDoubleLineEnd,
registry,
onSplitAtEnd,
} = props.current;
const { text, start, end } = value;

if ( onReplace && onSplit ) {
if ( event.shiftKey ) {
if ( ! disableLineBreaks ) {
event.preventDefault();
onChange( insert( value, '\n' ) );
}
} else if ( onSplitAtEnd && start === end && end === text.length ) {
// This is no longer used anywhere. Deprecate?
event.preventDefault();
onSplitAtEnd();
} else if ( onReplace && onSplit ) {
event.__deprecatedOnSplit = true;
} else if (
! supportsSplitting &&
! disableLineBreaks &&
! event.defaultPrevented
) {
event.preventDefault();
if (
// For some blocks it's desirable to split at the end of the
// block when there are two line breaks at the end of the
// block, so triple Enter exits the block.
onSplitAtDoubleLineEnd &&
start === end &&
end === text.length &&
text.slice( -2 ) === '\n\n'
) {
registry.batch( () => {
const _value = { ...value };
_value.start = _value.end - 2;
onChange( remove( _value ) );
onSplitAtDoubleLineEnd();
} );
} else {
onChange( insert( value, '\n' ) );
}
}
}

function onKeyDown( event ) {
function onDefaultKeyDown( event ) {
if ( event.defaultPrevented ) {
return;
}
Expand All @@ -32,53 +76,19 @@ export default ( props ) => ( element ) => {
return;
}

const {
value,
onChange,
disableLineBreaks,
onSplitAtEnd,
onSplitAtDoubleLineEnd,
registry,
} = props.current;

// On ENTER, we ALWAYS want to prevent the default browser behaviour
// at this last interception point.
event.preventDefault();

const { text, start, end } = value;

if ( event.shiftKey ) {
if ( ! disableLineBreaks ) {
onChange( insert( value, '\n' ) );
}
} else if ( onSplitAtEnd && start === end && end === text.length ) {
onSplitAtEnd();
} else if (
// For some blocks it's desirable to split at the end of the
// block when there are two line breaks at the end of the
// block, so triple Enter exits the block.
onSplitAtDoubleLineEnd &&
start === end &&
end === text.length &&
text.slice( -2 ) === '\n\n'
) {
registry.batch( () => {
const _value = { ...value };
_value.start = _value.end - 2;
onChange( remove( _value ) );
onSplitAtDoubleLineEnd();
} );
} else if ( ! disableLineBreaks ) {
onChange( insert( value, '\n' ) );
}
}

const { defaultView } = element.ownerDocument;

// Attach the listener to the window so parent elements have the chance to
// prevent the default behavior.
defaultView.addEventListener( 'keydown', onKeyDown );
element.addEventListener( 'keydown', onKeyDownDeprecated );
defaultView.addEventListener( 'keydown', onDefaultKeyDown );
element.addEventListener( 'keydown', onKeyDown );
return () => {
defaultView.removeEventListener( 'keydown', onKeyDown );
element.removeEventListener( 'keydown', onKeyDownDeprecated );
defaultView.removeEventListener( 'keydown', onDefaultKeyDown );
element.removeEventListener( 'keydown', onKeyDown );
};
};
11 changes: 7 additions & 4 deletions packages/block-editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { Content, valueToHTMLString } from './content';
import { withDeprecations } from './with-deprecations';
import { canBindBlock } from '../../utils/block-bindings';
import BlockContext from '../block-context';
import { PrivateBlockContext } from '../block-list/private-block-context';

export const keyboardShortcutContext = createContext();
export const inputEventContext = createContext();
Expand Down Expand Up @@ -77,7 +78,7 @@ function removeNativeProps( props ) {
return restProps;
}

export function RichTextWrapper(
function _RichTextWrapper(
{
children,
tagName = 'div',
Expand Down Expand Up @@ -118,6 +119,7 @@ export function RichTextWrapper(
} );
}

const { supportsSplitting } = useContext( PrivateBlockContext );
const instanceId = useInstanceId( RichTextWrapper );
const anchorRef = useRef();
const context = useBlockEditContext();
Expand Down Expand Up @@ -471,6 +473,7 @@ export function RichTextWrapper(
onSplitAtDoubleLineEnd,
keyboardShortcuts,
inputEvents,
supportsSplitting,
} ),
anchorRef,
] ) }
Expand Down Expand Up @@ -498,11 +501,11 @@ export function RichTextWrapper(
);
}

export const RichTextWrapper = forwardRef( _RichTextWrapper );

// This is the private API for the RichText component.
// It allows access to all props, not just the public ones.
export const PrivateRichText = withDeprecations(
forwardRef( RichTextWrapper )
);
export const PrivateRichText = withDeprecations( RichTextWrapper );

PrivateRichText.Content = Content;
PrivateRichText.isEmpty = ( value ) => {
Expand Down
Loading
Loading