Skip to content

Commit

Permalink
Rich text: extract delete handler to hook (#48273)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Feb 21, 2023
1 parent 6b0a217 commit b935741
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 );
};
}, [] );
}

1 comment on commit b935741

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in b935741.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4231892730
📝 Reported issues:

Please sign in to comment.