JSFiddle - React, Tailwind, and code Playground
HTML
<!doctype html>
<meta charset=utf8>
<link rel=stylesheet href="https://prosemirror.net/css/editor.css">
<script src="https://prosemirror.net/examples/prosemirror.js"></script>
<script src="require-pm.js"></script>
<script src="index.js" defer></script>
<base href="http://prosemirror.net/">
<div id=editor style="margin-bottom: 23px"></div>
<div style="display: none" id="content">
<p>a</p>
<div class="widget" data-num="1"></div>
<div class="widget" data-num="2"></div>
<div class="widget" data-num="3"></div>
<div class="widget" data-num="4"></div>
<p>a</p>
<p>a</p>
<p>a</p>
</div>
CSS
.widget {
position: relative;
margin-top: 5px;
margin-bottom: 5px;
}
.drag-handle {
position: absolute;
background-color: red;
top:0;
left:-30px;
width: 20px;
height: 20px
}
.ProseMirror {
}
.ProseMirror > * {
margin-left: 60px;
}
.ProseMirror-selectednode {
border: 1px solid blue;
}
JavaScript
const {EditorState} = require("prosemirror-state")
const {EditorView} = require("prosemirror-view")
const {Schema, DOMParser} = require("prosemirror-model")
const {schema} = require("prosemirror-schema-basic")
const {addListNodes} = require("prosemirror-schema-list")
const {exampleSetup} = require("prosemirror-example-setup")
// Mix the nodes from prosemirror-schema-list into the basic schema to
// create a schema with list support.
const mySchema = new Schema({
nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block").append({widget: {
attrs: {
num: { default: null },
},
group: 'block',
inline: false,
defining: true,
draggable: true,
selectable: true,
toDOM: ({ attrs }) => ['div', {class:'widget', 'data-num': attrs.num}],
parseDOM: [{
tag: 'div.widget',
getAttrs: (dom) => ({
num: parseInt(dom.dataset.num) || null
})
}]
} }),
marks: schema.spec.marks
})
let index = 1;
class Widget {
constructor(node, view, getPos) {
this.node = node;
this.view = view;
this.getPos = getPos;
this.dom = document.createElement('div');
this.dom.classList.add('widget');
const dragHandle = document.createElement('div');
dragHandle.classList.add('drag-handle');
this.dom.appendChild(dragHandle);
const content = document.createElement('div');
content.appendChild(document.createTextNode('hello world'+(node.attrs.num)));
this.dom.appendChild(content);
}
stopEvent(e) {
if (e.type === 'mousedown') {
this.downTarget = e.target;
}
if (e.type === 'dragstart' && this.downTarget && !this.downTarget.closest('.drag-handle')) {
e.preventDefault();
return;
}
if (e.type === 'dragend') {
this.downTarget = null;
}
return !/mousedown|drag|drop/.test(e.type);
}
}
window.view = new EditorView(document.querySelector("#editor"), {
state: EditorState.create({
doc:...