diff --git a/packages/slate-react/src/components/content.js b/packages/slate-react/src/components/content.js index 1c8f20b02..50a566b4d 100644 --- a/packages/slate-react/src/components/content.js +++ b/packages/slate-react/src/components/content.js @@ -199,6 +199,7 @@ class Content extends React.Component { debug.update('componentDidUpdate') this.updateSelection() + this.props.editor.clearUserActionPerformed() this.props.onEvent('onComponentDidUpdate') } @@ -342,8 +343,11 @@ class Content extends React.Component { native.addRange(range) } - // Scroll to the selection, in case it's out of view. - scrollToSelection(native) + // Only scroll to selection when a user action is performed + if (editor.userActionPerformed() === true) { + // Scroll to the selection, in case it's out of view. + scrollToSelection(native) + } // Then unset the `isUpdatingSelection` flag after a delay, to ensure that // it is still set when selection-related events from updating it fire. diff --git a/packages/slate-react/src/plugins/dom/before.js b/packages/slate-react/src/plugins/dom/before.js index 86c85752b..3faf78dff 100644 --- a/packages/slate-react/src/plugins/dom/before.js +++ b/packages/slate-react/src/plugins/dom/before.js @@ -30,6 +30,7 @@ function BeforePlugin() { let isComposing = false let isCopying = false let isDragging = false + let isUserActionPerformed = false /** * On before input. @@ -42,6 +43,7 @@ function BeforePlugin() { function onBeforeInput(event, editor, next) { const isSynthetic = !!event.nativeEvent if (editor.readOnly) return + isUserActionPerformed = true // COMPAT: If the browser supports Input Events Level 2, we will have // attached a custom handler for the real `beforeinput` events, instead of @@ -111,6 +113,7 @@ function BeforePlugin() { function onCompositionEnd(event, editor, next) { const n = compositionCount + isUserActionPerformed = true // The `count` check here ensures that if another composition starts // before the timeout has closed out this one, we will abort unsetting the @@ -134,6 +137,7 @@ function BeforePlugin() { function onClick(event, editor, next) { debug('onClick', { event }) + isUserActionPerformed = true next() } @@ -151,6 +155,7 @@ function BeforePlugin() { const { value } = editor const { selection } = value + isUserActionPerformed = true if (!selection.isCollapsed) { // https://github.com/ianstormtaylor/slate/issues/1879 @@ -322,6 +327,7 @@ function BeforePlugin() { function onDrop(event, editor, next) { if (editor.readOnly) return + isUserActionPerformed = true // Prevent default so the DOM's value isn't corrupted. event.preventDefault() @@ -371,6 +377,7 @@ function BeforePlugin() { function onInput(event, editor, next) { if (isComposing) return if (editor.value.selection.isBlurred) return + isUserActionPerformed = true debug('onInput', { event }) next() } @@ -415,6 +422,7 @@ function BeforePlugin() { event.preventDefault() } + isUserActionPerformed = true debug('onKeyDown', { event }) next() } @@ -429,6 +437,7 @@ function BeforePlugin() { function onPaste(event, editor, next) { if (editor.readOnly) return + isUserActionPerformed = true // Prevent defaults so the DOM state isn't corrupted. event.preventDefault() @@ -454,11 +463,21 @@ function BeforePlugin() { // Save the new `activeElement`. const window = getWindow(event.target) activeElement = window.document.activeElement + isUserActionPerformed = true debug('onSelect', { event }) next() } + function userActionPerformed() { + return isUserActionPerformed + } + + function clearUserActionPerformed() { + isUserActionPerformed = false + return null + } + /** * Return the plugin. * @@ -485,6 +504,8 @@ function BeforePlugin() { onKeyDown, onPaste, onSelect, + queries: { userActionPerformed }, + commands: { clearUserActionPerformed }, } }