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 870bfe170635c0..44d7ea568dfc39 100644 --- a/packages/rich-text/src/component/use-input-and-selection.js +++ b/packages/rich-text/src/component/use-input-and-selection.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useRef } from '@wordpress/element'; -import { useRefEffect } from '@wordpress/compose'; +import { debounce, useRefEffect } from '@wordpress/compose'; /** * Internal dependencies @@ -65,51 +65,55 @@ export function useInputAndSelection( props ) { let isComposing = false; - function onInput( event ) { - // Do not trigger a change if characters are being composed. - // Browsers will usually emit a final `input` event when the - // characters are composed. - // As of December 2019, Safari doesn't support - // nativeEvent.isComposing. - if ( isComposing ) { - return; - } - - let inputType; - - if ( event ) { - inputType = event.inputType; - } + const onInput = debounce( + ( event ) => { + // Do not trigger a change if characters are being composed. + // Browsers will usually emit a final `input` event when the + // characters are composed. + // As of December 2019, Safari doesn't support + // nativeEvent.isComposing. + if ( isComposing ) { + return; + } - const { record, applyRecord, createRecord, handleChange } = - propsRef.current; + let inputType; - // The browser formatted something or tried to insert HTML. - // Overwrite it. It will be handled later by the format library if - // needed. - if ( - inputType && - ( inputType.indexOf( 'format' ) === 0 || - INSERTION_INPUT_TYPES_TO_IGNORE.has( inputType ) ) - ) { - applyRecord( record.current ); - return; - } + if ( event ) { + inputType = event.inputType; + } - const currentValue = createRecord(); - const { start, activeFormats: oldActiveFormats = [] } = - record.current; + const { record, applyRecord, createRecord, handleChange } = + propsRef.current; - // Update the formats between the last and new caret position. - const change = updateFormats( { - value: currentValue, - start, - end: currentValue.start, - formats: oldActiveFormats, - } ); + // The browser formatted something or tried to insert HTML. + // Overwrite it. It will be handled later by the format library if + // needed. + if ( + inputType && + ( inputType.indexOf( 'format' ) === 0 || + INSERTION_INPUT_TYPES_TO_IGNORE.has( inputType ) ) + ) { + applyRecord( record.current ); + return; + } - handleChange( change ); - } + const currentValue = createRecord(); + const { start, activeFormats: oldActiveFormats = [] } = + record.current; + + // Update the formats between the last and new caret position. + const change = updateFormats( { + value: currentValue, + start, + end: currentValue.start, + formats: oldActiveFormats, + } ); + + handleChange( change ); + }, + 1, + { leading: true, trailing: false } + ); /** * Syncs the selection to local state. A callback for the