From 7509815f57c3860cea9c03c7397bde729832cadd Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 15 Jan 2025 12:53:51 +0200 Subject: [PATCH] Forms: Handle `Enter` on empty radio/checkbox input --- ...handle-enter-on-empty-radio-checkbox-items | 4 ++ .../jetpack-field-choice/item/edit.js | 70 ++++++++++++++++--- 2 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 projects/packages/forms/changelog/update-forms-handle-enter-on-empty-radio-checkbox-items diff --git a/projects/packages/forms/changelog/update-forms-handle-enter-on-empty-radio-checkbox-items b/projects/packages/forms/changelog/update-forms-handle-enter-on-empty-radio-checkbox-items new file mode 100644 index 0000000000000..68dbd11c08013 --- /dev/null +++ b/projects/packages/forms/changelog/update-forms-handle-enter-on-empty-radio-checkbox-items @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Forms: Handle `Enter` on empty radio/checkbox input diff --git a/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-choice/item/edit.js b/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-choice/item/edit.js index ebd2d342f869c..6dbebe841dc0e 100644 --- a/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-choice/item/edit.js +++ b/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-choice/item/edit.js @@ -1,13 +1,64 @@ -import { RichText, useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; -import { createBlock } from '@wordpress/blocks'; +import { + RichText, + useBlockProps, + useInnerBlocksProps, + store as blockEditorStore, +} from '@wordpress/block-editor'; +import { createBlock, cloneBlock, getDefaultBlockName } from '@wordpress/blocks'; +import { useRefEffect } from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; +import { useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import clsx from 'clsx'; -import { first } from 'lodash'; import { supportsParagraphSplitting } from '../../../util/block-support'; import { useParentAttributes } from '../../../util/use-parent-attributes'; import { useJetpackFieldStyles } from '../../use-jetpack-field-styles'; +function useEnter( props ) { + const { replaceBlocks, selectionChange } = useDispatch( blockEditorStore ); + const { getBlock, getBlockRootClientId, getBlockIndex } = useSelect( blockEditorStore ); + const propsRef = useRef( props ); + propsRef.current = props; + return useRefEffect( element => { + function onKeyDown( event ) { + // Keycode for ENTER is `13`. + if ( event.defaultPrevented || event.keyCode !== 13 ) { + return; + } + const { content, clientId } = propsRef.current; + if ( content?.length ) { + return; + } + event.preventDefault(); + const topParentBlock = getBlock( getBlockRootClientId( clientId ) ); + const blockIndex = getBlockIndex( clientId ); + const head = cloneBlock( { + ...topParentBlock, + innerBlocks: topParentBlock.innerBlocks.slice( 0, blockIndex ), + } ); + const middle = createBlock( getDefaultBlockName() ); + const after = topParentBlock.innerBlocks.slice( blockIndex + 1 ); + const tail = after.length + ? [ + cloneBlock( { + ...topParentBlock, + innerBlocks: after, + } ), + ] + : []; + replaceBlocks( topParentBlock.clientId, [ head, middle, ...tail ], 1 ); + // We manually change the selection here because we are replacing + // a different block than the selected one. + selectionChange( middle.clientId ); + } + + element.addEventListener( 'keydown', onKeyDown ); + return () => { + element.removeEventListener( 'keydown', onKeyDown ); + }; + }, [] ); +} + export default function JetpackFieldChoiceItemEdit( { attributes, clientId, @@ -16,14 +67,13 @@ export default function JetpackFieldChoiceItemEdit( { setAttributes, type, } ) { - const { removeBlock } = useDispatch( 'core/block-editor' ); + const { removeBlock } = useDispatch( blockEditorStore ); const parentAttributes = useParentAttributes( clientId ); const { optionStyle } = useJetpackFieldStyles( parentAttributes ); const siblingsCount = useSelect( select => { - const blockEditor = select( 'core/block-editor' ); - const parentBlockId = first( blockEditor.getBlockParents( clientId, true ) ); - return blockEditor.getBlock( parentBlockId ).innerBlocks.length; + const { getBlockCount, getBlockRootClientId } = select( blockEditorStore ); + return getBlockCount( getBlockRootClientId( clientId ) ); }, [ clientId ] ); @@ -51,21 +101,21 @@ export default function JetpackFieldChoiceItemEdit( { className: classes, style: optionStyle, } ); - + const useEnterRef = useEnter( { content: attributes.label, clientId } ); return ( <>
  • setAttributes( { label: newLabel } ) } preserveWhiteSpace={ false } - withoutInteractiveFormatting onRemove={ handleDelete } onReplace={ onReplace } { ...( supportsSplitting ? {} : { onSplit: handleSplit } ) }