diff --git a/examples/images/index.js b/examples/images/index.js index 4db6e8b9d..7ab436927 100644 --- a/examples/images/index.js +++ b/examples/images/index.js @@ -178,29 +178,9 @@ class Images extends React.Component { onDrop = (e, data, state, editor) => { switch (data.type) { case 'files': return this.onDropOrPasteFiles(e, data, state, editor) - case 'node': return this.onDropNode(e, data, state) } } - /** - * On drop node, insert the node wherever it is dropped. - * - * @param {Event} e - * @param {Object} data - * @param {State} state - * @return {State} - */ - - onDropNode = (e, data, state) => { - return state - .transform() - .deselect() - .removeNodeByKey(data.node.key) - .select(data.target) - .insertBlock(data.node) - .apply() - } - /** * On drop or paste files, read and insert the image files. * diff --git a/src/components/node.js b/src/components/node.js index 64327abf2..301f1ee8e 100644 --- a/src/components/node.js +++ b/src/components/node.js @@ -211,6 +211,12 @@ class Node extends React.Component { onDragStart = (e) => { const { node } = this.props + + // Only void node are draggable + if (!node.isVoid) { + return + } + const encoded = Base64.serializeNode(node, { preserveKeys: true }) const data = e.nativeEvent.dataTransfer data.setData(TYPES.NODE, encoded) diff --git a/src/plugins/core.js b/src/plugins/core.js index 9f2d10ad9..7e14c41c3 100644 --- a/src/plugins/core.js +++ b/src/plugins/core.js @@ -341,9 +341,49 @@ function Plugin(options = {}) { return onDropText(e, data, state) case 'fragment': return onDropFragment(e, data, state) + case 'node': + return onDropNode(e, data, state) } } + /** + * On drop node, insert the node wherever it is dropped. + * + * @param {Event} e + * @param {Object} data + * @param {State} state + * @return {State} + */ + + function onDropNode(e, data, state) { + debug('onDropNode', { data }) + + const { selection } = state + let { node, target, isInternal } = data + + // If the drag is internal and the target is after the selection, it + // needs to account for the selection's content being deleted. + if ( + isInternal && + selection.endKey == target.endKey && + selection.endOffset < target.endOffset + ) { + target = target.move(selection.startKey == selection.endKey + ? 0 - selection.endOffset - selection.startOffset + : 0 - selection.endOffset) + } + + const transform = state.transform() + + if (isInternal) transform.delete() + + return transform + .select(target) + .insertBlock(node) + .removeNodeByKey(node.key) + .apply() + } + /** * On drop fragment. *