From b39c8c3772431eb85d804d60ad00933ccdd4893c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20van=C2=A0Durpe?= <4710635+ellatrix@users.noreply.github.com> Date: Fri, 29 Apr 2022 12:27:29 +0300 Subject: [PATCH] Quote v2: implement exiting on Enter at end (#39911) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Riad Benguella Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- packages/block-library/src/paragraph/edit.js | 6 + .../block-library/src/paragraph/use-enter.js | 103 ++++++++++++++++++ packages/block-library/src/quote/block.json | 1 + 3 files changed, 110 insertions(+) create mode 100644 packages/block-library/src/paragraph/use-enter.js diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index c6a2988a3d064..d6c79cfe26292 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -23,6 +23,11 @@ import { import { createBlock } from '@wordpress/blocks'; import { formatLtr } from '@wordpress/icons'; +/** + * Internal dependencies + */ +import { useOnEnter } from './use-enter'; + const name = 'core/paragraph'; function ParagraphRTLControl( { direction, setDirection } ) { @@ -57,6 +62,7 @@ function ParagraphBlock( { const { align, content, direction, dropCap, placeholder } = attributes; const isDropCapFeatureEnabled = useSetting( 'typography.dropCap' ); const blockProps = useBlockProps( { + ref: useOnEnter( { clientId, content } ), className: classnames( { 'has-drop-cap': dropCap, [ `has-text-align-${ align }` ]: align, diff --git a/packages/block-library/src/paragraph/use-enter.js b/packages/block-library/src/paragraph/use-enter.js new file mode 100644 index 0000000000000..22bef120ef17c --- /dev/null +++ b/packages/block-library/src/paragraph/use-enter.js @@ -0,0 +1,103 @@ +/** + * WordPress dependencies + */ +import { useRef } from '@wordpress/element'; +import { useRefEffect } from '@wordpress/compose'; +import { ENTER } from '@wordpress/keycodes'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { hasBlockSupport, createBlock } from '@wordpress/blocks'; + +export function useOnEnter( props ) { + const { batch } = useRegistry(); + const { + moveBlocksToPosition, + replaceInnerBlocks, + duplicateBlocks, + insertBlock, + } = useDispatch( blockEditorStore ); + const { + getBlockRootClientId, + getBlockIndex, + getBlockOrder, + getBlockName, + getBlock, + getNextBlockClientId, + } = useSelect( blockEditorStore ); + const propsRef = useRef( props ); + propsRef.current = props; + return useRefEffect( ( element ) => { + function onKeyDown( event ) { + if ( event.defaultPrevented ) { + return; + } + + if ( event.keyCode !== ENTER ) { + return; + } + + const { content, clientId } = propsRef.current; + + // The paragraph should be empty. + if ( content.length ) { + return; + } + + const wrapperClientId = getBlockRootClientId( clientId ); + + if ( + ! hasBlockSupport( + getBlockName( wrapperClientId ), + '__experimentalOnEnter', + false + ) + ) { + return; + } + + const order = getBlockOrder( wrapperClientId ); + + event.preventDefault(); + + const position = order.indexOf( clientId ); + + // If it is the last block, exit. + if ( position === order.length - 1 ) { + moveBlocksToPosition( + [ clientId ], + wrapperClientId, + getBlockRootClientId( wrapperClientId ), + getBlockIndex( wrapperClientId ) + 1 + ); + return; + } + + // If it is in the middle, split the block in two. + const wrapperBlock = getBlock( wrapperClientId ); + batch( () => { + duplicateBlocks( [ wrapperClientId ] ); + const blockIndex = getBlockIndex( wrapperClientId ); + + replaceInnerBlocks( + wrapperClientId, + wrapperBlock.innerBlocks.slice( 0, position ) + ); + replaceInnerBlocks( + getNextBlockClientId( wrapperClientId ), + wrapperBlock.innerBlocks.slice( position + 1 ) + ); + insertBlock( + createBlock( 'core/paragraph' ), + blockIndex + 1, + getBlockRootClientId( wrapperClientId ), + true + ); + } ); + } + + element.addEventListener( 'keydown', onKeyDown ); + return () => { + element.removeEventListener( 'keydown', onKeyDown ); + }; + }, [] ); +} diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json index 74b72078c5c45..c4726f3cdaa0c 100644 --- a/packages/block-library/src/quote/block.json +++ b/packages/block-library/src/quote/block.json @@ -30,6 +30,7 @@ "supports": { "anchor": true, "__experimentalSlashInserter": true, + "__experimentalOnEnter": true, "typography": { "fontSize": true, "lineHeight": true,