2022-09-09 11:53:35 +00:00
|
|
|
import { Plugin, NodeSelection } from 'prosemirror-state'
|
|
|
|
import { DecorationSet, Decoration } from 'prosemirror-view'
|
2022-10-19 17:26:07 +00:00
|
|
|
import { ProseMirrorExtension } from '../helpers'
|
|
|
|
|
|
|
|
const handleIcon = `
|
|
|
|
<svg viewBox="0 0 10 10" height="14" width="14">
|
|
|
|
<path d="M3 2a1 1 0 110-2 1 1 0 010 2zm0 4a1 1 0 110-2 1 1 0 010 2zm0 4a1 1 0 110-2 1 1 0 010 2zm4-8a1 1 0 110-2 1 1 0 010 2zm0 4a1 1 0 110-2 1 1 0 010 2zm0 4a1 1 0 110-2 1 1 0 010 2z"/>
|
|
|
|
</svg>`
|
2022-09-09 11:53:35 +00:00
|
|
|
|
|
|
|
const createDragHandle = () => {
|
|
|
|
const handle = document.createElement('span')
|
|
|
|
handle.setAttribute('contenteditable', 'false')
|
|
|
|
const icon = document.createElement('span')
|
|
|
|
icon.innerHTML = handleIcon
|
2022-10-09 00:00:13 +00:00
|
|
|
handle.appendChild(icon)
|
2022-09-09 11:53:35 +00:00
|
|
|
handle.classList.add('handle')
|
|
|
|
return handle
|
|
|
|
}
|
|
|
|
|
|
|
|
const handlePlugin = new Plugin({
|
|
|
|
props: {
|
|
|
|
decorations(state) {
|
|
|
|
const decos = []
|
|
|
|
state.doc.forEach((node, pos) => {
|
2022-10-19 17:26:07 +00:00
|
|
|
decos.push(Decoration.widget(pos + 1, createDragHandle))
|
2022-09-09 11:53:35 +00:00
|
|
|
decos.push(
|
|
|
|
Decoration.node(pos, pos + node.nodeSize, {
|
|
|
|
class: 'draggable'
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
return DecorationSet.create(state.doc, decos)
|
|
|
|
},
|
|
|
|
handleDOMEvents: {
|
|
|
|
mousedown: (editorView, event) => {
|
|
|
|
const target = event.target as Element
|
|
|
|
if (target.classList.contains('handle')) {
|
|
|
|
const pos = editorView.posAtCoords({ left: event.x, top: event.y })
|
|
|
|
const resolved = editorView.state.doc.resolve(pos.pos)
|
|
|
|
const tr = editorView.state.tr
|
|
|
|
tr.setSelection(NodeSelection.create(editorView.state.doc, resolved.before()))
|
|
|
|
editorView.dispatch(tr)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
export default (): ProseMirrorExtension => ({
|
|
|
|
plugins: (prev) => [...prev, handlePlugin]
|
|
|
|
})
|