fix bubble menu

This commit is contained in:
Philipp Kühn 2018-10-22 18:24:54 +02:00
parent 3718591d33
commit a2dd57ad09
4 changed files with 97 additions and 1 deletions

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="editor"> <div class="editor">
<menu-bubble class="menubar" :editor="editor"> <menu-bubble class="menububble" :editor="editor">
<template slot-scope="{ nodes, marks }"> <template slot-scope="{ nodes, marks }">
<button <button

View File

@ -1,3 +1,5 @@
import MenuBubble from '../Utils/MenuBubble'
export default { export default {
props: { props: {
editor: { editor: {
@ -5,6 +7,18 @@ export default {
type: Object, type: Object,
}, },
}, },
watch: {
editor: {
immediate: true,
handler(editor) {
if (editor) {
this.$nextTick(() => {
editor.registerPlugin(MenuBubble(this.$el))
})
}
},
}
},
render(createElement) { render(createElement) {
if (this.editor) { if (this.editor) {
return createElement('div', this.$scopedSlots.default({ return createElement('div', this.$scopedSlots.default({

View File

@ -247,6 +247,16 @@ export default class Editor {
this.bus.$on(event, callback) this.bus.$on(event, callback)
} }
registerPlugin(plugin = null) {
if (plugin) {
this.plugins = this.plugins.concat([plugin])
this.state = this.state.reconfigure({
plugins: this.plugins,
})
this.view.updateState(this.state)
}
}
destroy() { destroy() {
this.emit('destroy') this.emit('destroy')

View File

@ -0,0 +1,72 @@
import { Plugin } from 'prosemirror-state'
class Toolbar {
constructor({ element, editorView }) {
this.editorView = editorView
this.element = element
this.element.style.visibility = 'hidden'
this.element.style.opacity = 0
this.editorView.dom.addEventListener('blur', this.hide.bind(this))
}
update(view, lastState) {
const { state } = view
// Don't do anything if the document/selection didn't change
if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) {
return
}
// Hide the tooltip if the selection is empty
if (state.selection.empty) {
this.hide()
return
}
// Otherwise, reposition it and update its content
this.show()
const { from, to } = state.selection
// These are in screen coordinates
const start = view.coordsAtPos(from)
const end = view.coordsAtPos(to)
// The box in which the tooltip is positioned, to use as base
const box = this.element.offsetParent.getBoundingClientRect()
// Find a center-ish x position from the selection endpoints (when
// crossing lines, end may be more to the left)
const left = Math.max((start.left + end.left) / 2, start.left + 3)
this.element.style.left = `${left - box.left}px`
this.element.style.bottom = `${box.bottom - start.top}px`
}
show() {
this.element.style.visibility = 'visible'
this.element.style.opacity = 1
}
hide(event) {
if (event && event.relatedTarget) {
return
}
this.element.style.visibility = 'hidden'
this.element.style.opacity = 0
}
destroy() {
this.editorView.dom.removeEventListener('blur', this.hide)
}
}
export default function (element) {
return new Plugin({
view(editorView) {
return new Toolbar({ editorView, element })
},
})
}