From 4e6ca3953b295aa5b037c14859ed5fe61d4bccdf Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Mon, 1 Aug 2016 18:09:30 -0700 Subject: [PATCH] fix onBeforeInput decorations logic, fix initial onSelect logic --- lib/components/content.js | 8 +++-- lib/plugins/core.js | 61 ++++++++++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/lib/components/content.js b/lib/components/content.js index 132e84d3c..8fd5dc01e 100644 --- a/lib/components/content.js +++ b/lib/components/content.js @@ -127,7 +127,7 @@ class Content extends React.Component { componentDidUpdate = (props, state) => { setTimeout(() => { this.tmp.isRendering = false - }) + }, 1) } /** @@ -454,6 +454,7 @@ class Content extends React.Component { */ onInput = (e) => { + if (this.tmp.isRendering) return if (this.tmp.isComposing) return if (isNonEditable(e)) return debug('onInput') @@ -648,7 +649,8 @@ class Content extends React.Component { anchor.key == selection.anchorKey && anchor.offset == selection.anchorOffset && focus.key == selection.focusKey && - focus.offset == selection.focusOffset + focus.offset == selection.focusOffset && + selection.isFocused ) { return } @@ -667,7 +669,7 @@ class Content extends React.Component { .normalize(document) } - debug('onSelect', data) + debug('onSelect', { data, selection: data.selection.toJS() }) this.props.onSelect(e, data) } diff --git a/lib/plugins/core.js b/lib/plugins/core.js index fd1278e5a..4a545e72b 100644 --- a/lib/plugins/core.js +++ b/lib/plugins/core.js @@ -1,10 +1,19 @@ import Base64 from '../serializers/base-64' import Character from '../models/character' +import Debug from 'debug' import Placeholder from '../components/placeholder' import React from 'react' import String from '../utils/string' +/** + * Debug. + * + * @type {Function} + */ + +const debug = Debug('slate:core') + /** * The default plugin. * @@ -79,12 +88,17 @@ function Plugin(options = {}) { const { startOffset, startText, startBlock } = state // Determine what the characters would be if natively inserted. - const prev = startText.getDecoratedCharacters(startBlock, renderDecorations) - const char = prev.get(startOffset) - const chars = prev + const prevChars = startText.getDecoratedCharacters(startBlock, renderDecorations) + const prevChar = prevChars.get(startOffset - 1) + const char = Character.create({ + text: e.data, + marks: prevChar && prevChar.marks + }) + + const chars = prevChars .slice(0, startOffset) - .push(Character.create({ text: e.data, marks: char && char.marks })) - .concat(prev.slice(startOffset)) + .push(char) + .concat(prevChars.slice(startOffset)) // Determine what the characters should be, if not natively inserted. let next = state @@ -114,7 +128,7 @@ function Plugin(options = {}) { // If not native, prevent default so that the DOM remains untouched. if (!isNative) e.preventDefault() - // Return the new state. + debug('onBeforeInput', { data, isNative }) return next } @@ -128,10 +142,14 @@ function Plugin(options = {}) { */ function onBlur(e, data, state) { + const isNative = true + + debug('onBlur', { data, isNative }) + return state .transform() .blur() - .apply({ isNative: true }) + .apply({ isNative }) } /** @@ -144,6 +162,7 @@ function Plugin(options = {}) { */ function onCopy(e, data, state) { + debug('onCopy', data) onCutOrCopy(e, data, state) } @@ -158,6 +177,7 @@ function Plugin(options = {}) { */ function onCut(e, data, state, editor) { + debug('onCut', data) onCutOrCopy(e, data, state) // Once the fake cut content has successfully been added to the clipboard, @@ -238,6 +258,8 @@ function Plugin(options = {}) { */ function onDrop(e, data, state) { + debug('onDrop', { data }) + switch (data.type) { case 'text': case 'html': @@ -257,6 +279,8 @@ function Plugin(options = {}) { */ function onDropFragment(e, data, state) { + debug('onDropFragment', { data }) + const { selection } = state let { fragment, target, isInternal } = data @@ -292,6 +316,8 @@ function Plugin(options = {}) { */ function onDropText(e, data, state) { + debug('onDropText', { data }) + const { text, target } = data let transform = state .transform() @@ -317,6 +343,8 @@ function Plugin(options = {}) { */ function onKeyDown(e, data, state) { + debug('onKeyDown', { data }) + switch (data.key) { case 'enter': return onKeyDownEnter(e, data, state) case 'backspace': return onKeyDownBackspace(e, data, state) @@ -336,6 +364,8 @@ function Plugin(options = {}) { */ function onKeyDownEnter(e, data, state) { + debug('onKeyDownEnter', { data }) + const { document, startKey, startBlock } = state // For void blocks, we don't want to split. Instead we just move to the @@ -365,6 +395,7 @@ function Plugin(options = {}) { */ function onKeyDownBackspace(e, data, state) { + debug('onKeyDownBackspace', { data }) // If expanded, delete regularly. if (state.isExpanded) { @@ -407,6 +438,7 @@ function Plugin(options = {}) { */ function onKeyDownDelete(e, data, state) { + debug('onKeyDownDelete', { data }) // If expanded, delete regularly. if (state.isExpanded) { @@ -450,6 +482,9 @@ function Plugin(options = {}) { function onKeyDownY(e, data, state) { if (!data.isMod) return + + debug('onKeyDownY', { data }) + return state .transform() .redo() @@ -466,6 +501,9 @@ function Plugin(options = {}) { function onKeyDownZ(e, data, state) { if (!data.isMod) return + + debug('onKeyDownZ', { data }) + return state .transform() [data.isShift ? 'redo' : 'undo']() @@ -481,6 +519,8 @@ function Plugin(options = {}) { */ function onPaste(e, data, state) { + debug('onPaste', { data }) + switch (data.type) { case 'fragment': return onPasteFragment(e, data, state) @@ -500,6 +540,8 @@ function Plugin(options = {}) { */ function onPasteFragment(e, data, state) { + debug('onPasteFragment', { data }) + return state .transform() .insertFragment(data.fragment) @@ -516,6 +558,8 @@ function Plugin(options = {}) { */ function onPasteText(e, data, state) { + debug('onPasteText', { data }) + let transform = state.transform() data.text @@ -539,6 +583,9 @@ function Plugin(options = {}) { function onSelect(e, data, state) { const { selection } = data + + debug('onSelect', { data, selection: selection.toJS() }) + return state .transform() .moveTo(selection)