diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 042082fb19fbe1..66ef0c6bccb142 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -275,13 +275,7 @@ function RichTextWrapper( ); } - const { - value, - onChange, - onFocus, - ref: richTextRef, - hasActiveFormats, - } = useRichText( { + const { value, onChange, onFocus, ref: richTextRef } = useRichText( { value: adjustedValue, onChange( html, { __unstableFormats, __unstableText } ) { adjustedOnChange( html ); @@ -309,8 +303,8 @@ function RichTextWrapper( onChange, } ); - useCaretInFormat( hasActiveFormats ); - useMarkPersistent( { hasActiveFormats, html: adjustedValue, value } ); + useCaretInFormat( { value } ); + useMarkPersistent( { html: adjustedValue, value } ); function onKeyDown( event ) { const { keyCode } = event; @@ -372,6 +366,8 @@ function RichTextWrapper( } else 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 ( diff --git a/packages/block-editor/src/components/rich-text/use-caret-in-format.js b/packages/block-editor/src/components/rich-text/use-caret-in-format.js index 1d6256065d7df5..f5ad69f39713b7 100644 --- a/packages/block-editor/src/components/rich-text/use-caret-in-format.js +++ b/packages/block-editor/src/components/rich-text/use-caret-in-format.js @@ -9,7 +9,9 @@ import { useDispatch, useSelect } from '@wordpress/data'; */ import { store as blockEditorStore } from '../../store'; -export function useCaretInFormat( hasActiveFormats ) { +export function useCaretInFormat( { value } ) { + const hasActiveFormats = + value.activeFormats && !! value.activeFormats.length; const { isCaretWithinFormattedText } = useSelect( blockEditorStore ); const { enterFormattedText, exitFormattedText } = useDispatch( blockEditorStore diff --git a/packages/block-editor/src/components/rich-text/use-mark-persistent.js b/packages/block-editor/src/components/rich-text/use-mark-persistent.js index 48eb21108bce7a..6fbe28cdd7f351 100644 --- a/packages/block-editor/src/components/rich-text/use-mark-persistent.js +++ b/packages/block-editor/src/components/rich-text/use-mark-persistent.js @@ -9,8 +9,10 @@ import { useDispatch } from '@wordpress/data'; */ import { store as blockEditorStore } from '../../store'; -export function useMarkPersistent( { hasActiveFormats, html, value } ) { +export function useMarkPersistent( { html, value } ) { const previousText = useRef(); + const hasActiveFormats = + value.activeFormats && !! value.activeFormats.length; const { __unstableMarkLastChangeAsPersistent } = useDispatch( blockEditorStore ); diff --git a/packages/rich-text/src/component/index.js b/packages/rich-text/src/component/index.js index c671633d54c4ea..d258b8b33ca967 100644 --- a/packages/rich-text/src/component/index.js +++ b/packages/rich-text/src/component/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useRef, useState, useLayoutEffect } from '@wordpress/element'; +import { useRef, useLayoutEffect, useReducer } from '@wordpress/element'; import { useMergeRefs, useRefEffect } from '@wordpress/compose'; /** @@ -36,8 +36,8 @@ export function useRichText( { __unstableBeforeSerialize, __unstableAddInvisibleFormats, } ) { + const [ , forceRender ] = useReducer( () => ( {} ) ); const ref = useRef(); - const [ activeFormats = [], setActiveFormats ] = useState(); function createRecord() { const { @@ -121,13 +121,7 @@ export function useRichText( { record.current = newRecord; - const { - start, - end, - formats, - text, - activeFormats: newActiveFormats = [], - } = newRecord; + const { start, end, formats, text } = newRecord; // Selection must be updated first, so it is recorded in history when // the content change happens. @@ -136,7 +130,7 @@ export function useRichText( { __unstableFormats: formats, __unstableText: text, } ); - setActiveFormats( newActiveFormats ); + forceRender(); } function applyFromProps( { domOnly } = {} ) { @@ -182,11 +176,11 @@ export function useRichText( { const mergedRefs = useMergeRefs( [ ref, useDefaultStyle(), - useBoundaryStyle( { activeFormats } ), + useBoundaryStyle( { record } ), useInlineWarning(), useCopyHandler( { record, multilineTag, preserveWhiteSpace } ), useSelectObject(), - useFormatBoundaries( { record, applyRecord, setActiveFormats } ), + useFormatBoundaries( { record, applyRecord } ), useDelete( { createRecord, handleChange, @@ -204,7 +198,6 @@ export function useRichText( { handleChange, isSelected, onSelectionChange, - setActiveFormats, } ), useRefEffect( () => { if ( didMount.current ) { @@ -222,7 +215,6 @@ export function useRichText( { onChange: handleChange, onFocus: focus, ref: mergedRefs, - hasActiveFormats: activeFormats.length, }; } diff --git a/packages/rich-text/src/component/use-boundary-style.js b/packages/rich-text/src/component/use-boundary-style.js index 8a171f93f8a55f..214fd6862c1733 100644 --- a/packages/rich-text/src/component/use-boundary-style.js +++ b/packages/rich-text/src/component/use-boundary-style.js @@ -7,8 +7,9 @@ import { useEffect, useRef } from '@wordpress/element'; * Calculates and renders the format boundary style when the active formats * change. */ -export function useBoundaryStyle( { activeFormats } ) { +export function useBoundaryStyle( { record } ) { const ref = useRef(); + const { activeFormats = [] } = record.current; useEffect( () => { // There's no need to recalculate the boundary styles if no formats are // active, because no boundary styles will be visible. diff --git a/packages/rich-text/src/component/use-format-boundaries.js b/packages/rich-text/src/component/use-format-boundaries.js index c8dacf35dd7eb1..08937b7a881cb0 100644 --- a/packages/rich-text/src/component/use-format-boundaries.js +++ b/packages/rich-text/src/component/use-format-boundaries.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useRef } from '@wordpress/element'; +import { useRef, useReducer } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; import { LEFT, RIGHT } from '@wordpress/keycodes'; @@ -13,6 +13,7 @@ import { isCollapsed } from '../is-collapsed'; const EMPTY_ACTIVE_FORMATS = []; export function useFormatBoundaries( props ) { + const [ , forceRender ] = useReducer( () => ( {} ) ); const propsRef = useRef( props ); propsRef.current = props; return useRefEffect( ( element ) => { @@ -30,7 +31,7 @@ export function useFormatBoundaries( props ) { return; } - const { record, applyRecord, setActiveFormats } = propsRef.current; + const { record, applyRecord } = propsRef.current; const { text, formats, @@ -125,7 +126,7 @@ export function useFormatBoundaries( props ) { }; record.current = newValue; applyRecord( newValue ); - setActiveFormats( newActiveFormats ); + forceRender(); } element.addEventListener( 'keydown', onKeyDown ); diff --git a/packages/rich-text/src/component/use-input-and-selection.js b/packages/rich-text/src/component/use-input-and-selection.js index 36c7a2802d970e..7f011f6ecb73ab 100644 --- a/packages/rich-text/src/component/use-input-and-selection.js +++ b/packages/rich-text/src/component/use-input-and-selection.js @@ -80,10 +80,6 @@ export function useInputAndSelection( props ) { inputType = event.inputType; } - if ( ! inputType && event && event.nativeEvent ) { - inputType = event.nativeEvent.inputType; - } - const { record, applyRecord, @@ -138,7 +134,6 @@ export function useInputAndSelection( props ) { createRecord, isSelected, onSelectionChange, - setActiveFormats, } = propsRef.current; if ( event.type !== 'selectionchange' && ! isSelected ) { @@ -203,7 +198,6 @@ export function useInputAndSelection( props ) { record.current = newValue; applyRecord( newValue, { domOnly: true } ); onSelectionChange( start, end ); - setActiveFormats( newActiveFormats ); } function onCompositionStart() { @@ -230,12 +224,7 @@ export function useInputAndSelection( props ) { } function onFocus() { - const { - record, - isSelected, - onSelectionChange, - setActiveFormats, - } = propsRef.current; + const { record, isSelected, onSelectionChange } = propsRef.current; if ( ! isSelected ) { // We know for certain that on focus, the old selection is invalid. @@ -250,7 +239,6 @@ export function useInputAndSelection( props ) { activeFormats: EMPTY_ACTIVE_FORMATS, }; onSelectionChange( index, index ); - setActiveFormats( EMPTY_ACTIVE_FORMATS ); } else { onSelectionChange( record.current.start, record.current.end ); }