diff --git a/src/components/Widgets/MarkdownControlElements/RawEditor/index.css b/src/components/Widgets/MarkdownControlElements/RawEditor/index.css
index 6e91c9f0..f158b7f8 100644
--- a/src/components/Widgets/MarkdownControlElements/RawEditor/index.css
+++ b/src/components/Widgets/MarkdownControlElements/RawEditor/index.css
@@ -1,3 +1,22 @@
.root {
position: relative;
}
+
+.dragging { }
+
+.shim {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ border: 2px dashed #aaa;
+ background: rgba(0,0,0,0.2);
+}
+
+.dragging .shim {
+ z-index: 1000;
+ display: block;
+ pointer-events: none;
+}
diff --git a/src/components/Widgets/MarkdownControlElements/RawEditor/index.js b/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
index d921a4c1..ad9c2cf3 100644
--- a/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
+++ b/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
@@ -24,10 +24,6 @@ function processUrl(url) {
return `/${ url }`;
}
-function preventDefault(e) {
- e.preventDefault();
-}
-
function cleanupPaste(paste) {
const content = html.toContent(paste);
return markdown.toText(content);
@@ -76,11 +72,9 @@ export default class RawEditor extends React.Component {
},
};
}
+
componentDidMount() {
this.updateHeight();
- this.element.addEventListener('dragenter', preventDefault, false);
- this.element.addEventListener('dragover', preventDefault, false);
- this.element.addEventListener('drop', this.handleDrop, false);
this.element.addEventListener('paste', this.handlePaste, false);
}
@@ -93,9 +87,7 @@ export default class RawEditor extends React.Component {
}
componentWillUnmount() {
- this.element.removeEventListener('dragenter', preventDefault);
- this.element.removeEventListener('dragover', preventDefault);
- this.element.removeEventListener('drop', this.handleDrop);
+ this.element.removeEventListener('paste', this.handlePaste);
}
getSelection() {
@@ -256,8 +248,25 @@ export default class RawEditor extends React.Component {
};
}
+ handleDragEnter = (e) => {
+ e.preventDefault();
+ this.setState({ dragging: true });
+ };
+
+ handleDragLeave = (e) => {
+ e.preventDefault();
+ this.setState({ dragging: false });
+ };
+
+ handleDragOver = (e) => {
+ e.preventDefault();
+ };
+
handleDrop = (e) => {
e.preventDefault();
+
+ this.setState({ dragging: false });
+
let data;
if (e.dataTransfer.files && e.dataTransfer.files.length) {
@@ -296,8 +305,19 @@ export default class RawEditor extends React.Component {
render() {
const { onAddMedia, onRemoveMedia, getMedia } = this.props;
- const { showToolbar, showBlockMenu, plugins, selectionPosition } = this.state;
- return (
+ const { showToolbar, showBlockMenu, plugins, selectionPosition, dragging } = this.state;
+ const classNames = [styles.root];
+ if (dragging) {
+ classNames.push(styles.dragging);
+ }
+
+ return (
+
);
}
}
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.css b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.css
index 54764f89..9dc2e9b5 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.css
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.css
@@ -20,6 +20,13 @@
& p {
margin-bottom: 20px;
}
+ & hr {
+ border: 1px solid;
+ margin-bottom: 20px;
+ }
+ & li > p {
+ margin: 0;
+ }
& div[data-plugin] {
background: #fff;
border: 1px solid #aaa;
@@ -28,6 +35,25 @@
}
}
+.dragging { }
+
+.shim {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ border: 2px dashed #aaa;
+ background: rgba(0,0,0,0.2);
+}
+
+.dragging .shim {
+ z-index: 1000;
+ display: block;
+ pointer-events: none;
+}
+
:global {
& .ProseMirror {
position: relative;
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
index 17718916..216b30fc 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
@@ -11,6 +11,7 @@ import { keymap } from 'prosemirror-keymap';
import { schema, defaultMarkdownSerializer } from 'prosemirror-markdown';
import { baseKeymap, setBlockType, toggleMark } from 'prosemirror-commands';
import registry from '../../../../lib/registry';
+import MediaProxy from '../../../../valueObjects/MediaProxy';
import { buildKeymap } from './keymap';
import createMarkdownParser from './parser';
import Toolbar from '../Toolbar';
@@ -213,15 +214,71 @@ export default class Editor extends Component {
this.view.props.onAction(this.view.state.tr.replaceSelectionWith(nodeType.create(data.toJS())).action());
};
+ handleDragEnter = (e) => {
+ e.preventDefault();
+ this.setState({ dragging: true });
+ };
+
+ handleDragLeave = (e) => {
+ e.preventDefault();
+ this.setState({ dragging: false });
+ };
+
+ handleDragOver = (e) => {
+ e.preventDefault();
+ };
+
+ handleDrop = (e) => {
+ e.preventDefault();
+
+ this.setState({ dragging: false });
+
+ const { schema } = this.state;
+
+ const nodes = [];
+
+ if (e.dataTransfer.files && e.dataTransfer.files.length) {
+ Array.from(e.dataTransfer.files).forEach((file) => {
+ const mediaProxy = new MediaProxy(file.name, file);
+ this.props.onAddMedia(mediaProxy);
+ if (file.type.split('/')[0] === 'image') {
+ nodes.push(
+ schema.nodes.image.create({ src: mediaProxy.public_path, alt: file.name })
+ );
+ } else {
+ nodes.push(
+ schema.marks.link.create({ href: mediaProxy.public_path, title: file.name })
+ );
+ }
+ });
+ } else {
+ nodes.push(schema.nodes.paragraph.create({}, e.dataTransfer.getData('text/plain')));
+ }
+
+ nodes.forEach((node) => {
+ this.view.props.onAction(this.view.state.tr.replaceSelectionWith(node).action());
+ });
+ };
+
handleToggle = () => {
this.props.onMode('raw');
};
render() {
const { onAddMedia, onRemoveMedia, getMedia } = this.props;
- const { plugins, showToolbar, showBlockMenu, selectionPosition } = this.state;
+ const { plugins, showToolbar, showBlockMenu, selectionPosition, dragging } = this.state;
+ const classNames = [styles.editor];
+ if (dragging) {
+ classNames.push(styles.dragging);
+ }
- return (
+ return (
);
}
}
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/serializer.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/serializer.js
deleted file mode 100644
index e69de29b..00000000