Skip to content

Commit

Permalink
Rich text: extract delete handler to hook
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Feb 21, 2023
1 parent 8548085 commit 76014c6
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 43 deletions.
49 changes: 6 additions & 43 deletions packages/block-editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ import { useInstanceId, useMergeRefs } from '@wordpress/compose';
import {
__unstableUseRichText as useRichText,
__unstableCreateElement,
isEmpty,
isCollapsed,
removeFormat,
} from '@wordpress/rich-text';
import deprecated from '@wordpress/deprecated';
import { BACKSPACE, DELETE } from '@wordpress/keycodes';
import { Popover } from '@wordpress/components';

/**
Expand All @@ -39,6 +36,7 @@ import { useMarkPersistent } from './use-mark-persistent';
import { usePasteHandler } from './use-paste-handler';
import { useBeforeInputRules } from './use-before-input-rules';
import { useInputRules } from './use-input-rules';
import { useDelete } from './use-delete';
import { useEnter } from './use-enter';
import { useFormatTypes } from './use-format-types';
import { useRemoveBrowserShortcuts } from './use-remove-browser-shortcuts';
Expand Down Expand Up @@ -316,45 +314,6 @@ function RichTextWrapper(
const keyboardShortcuts = useRef( new Set() );
const inputEvents = useRef( new Set() );

function onKeyDown( event ) {
const { keyCode } = event;

if ( event.defaultPrevented ) {
return;
}

if ( keyCode === DELETE || keyCode === BACKSPACE ) {
const { start, end, text } = value;
const isReverse = keyCode === BACKSPACE;
const hasActiveFormats =
value.activeFormats && !! value.activeFormats.length;

// Only process delete if the key press occurs at an uncollapsed edge.
if (
! isCollapsed( value ) ||
hasActiveFormats ||
( isReverse && start !== 0 ) ||
( ! isReverse && end !== text.length )
) {
return;
}

if ( onMerge ) {
onMerge( ! isReverse );
}

// Only handle remove on Backspace. This serves dual-purpose of being
// an intentional user interaction distinguishing between Backspace and
// Delete to remove the empty field, but also to avoid merge & remove
// causing destruction of two fields (merge, then removed merged).
if ( onRemove && isEmpty( value ) && isReverse ) {
onRemove( ! isReverse );
}

event.preventDefault();
}
}

function onFocus() {
anchorRef.current?.focus();
}
Expand Down Expand Up @@ -428,6 +387,11 @@ function RichTextWrapper(
preserveWhiteSpace,
pastePlainText,
} ),
useDelete( {
value,
onMerge,
onRemove,
} ),
useEnter( {
removeEditorOnlyFormats,
value,
Expand All @@ -449,7 +413,6 @@ function RichTextWrapper(
props.className,
'rich-text'
) }
onKeyDown={ onKeyDown }
/>
</>
);
Expand Down
59 changes: 59 additions & 0 deletions packages/block-editor/src/components/rich-text/use-delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* WordPress dependencies
*/
import { useRef } from '@wordpress/element';
import { useRefEffect } from '@wordpress/compose';
import { DELETE, BACKSPACE } from '@wordpress/keycodes';
import { isCollapsed, isEmpty } from '@wordpress/rich-text';

export function useDelete( props ) {
const propsRef = useRef( props );
propsRef.current = props;
return useRefEffect( ( element ) => {
function onKeyDown( event ) {
const { keyCode } = event;

if ( event.defaultPrevented ) {
return;
}

const { value, onMerge, onRemove } = propsRef.current;

if ( keyCode === DELETE || keyCode === BACKSPACE ) {
const { start, end, text } = value;
const isReverse = keyCode === BACKSPACE;
const hasActiveFormats =
value.activeFormats && !! value.activeFormats.length;

// Only process delete if the key press occurs at an uncollapsed edge.
if (
! isCollapsed( value ) ||
hasActiveFormats ||
( isReverse && start !== 0 ) ||
( ! isReverse && end !== text.length )
) {
return;
}

if ( onMerge ) {
onMerge( ! isReverse );
}

// Only handle remove on Backspace. This serves dual-purpose of being
// an intentional user interaction distinguishing between Backspace and
// Delete to remove the empty field, but also to avoid merge & remove
// causing destruction of two fields (merge, then removed merged).
if ( onRemove && isEmpty( value ) && isReverse ) {
onRemove( ! isReverse );
}

event.preventDefault();
}
}

element.addEventListener( 'keydown', onKeyDown );
return () => {
element.removeEventListener( 'keydown', onKeyDown );
};
}, [] );
}

0 comments on commit 76014c6

Please sign in to comment.