Tiptap BubbleMenu 浮动菜单扩展,当选中对象菜单将悬浮在鼠标附近,你可以对选中的标记mark进行操作。
npm install @tiptap/extension-bubble-menu
element 包含菜单的元素,默认为null。
BubbleMenu.configure({
element: null,
})
updateDelay BubbleMenu取消了更新方法,允许在每次选择更新时不更新气泡菜单。这可以在毫秒内控制。BubbleMenuPlugin的默认延迟为250ms。这可以通过将延迟设置为0来停用。
BubbleMenu.configure({
updateDelay: 0,
})
tippyOptions BubbleMenu使用tippy.js,您可以直接将配置传递给它。
BubbleMenu.configure({
tippyOptions: { },
})
pluginKey 当有多个实例时你需要用到这个参数,默认为bubbleMenu。
import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'
new Editor({
extensions: [
BubbleMenu.configure({
pluginKey: 'bubbleMenuOne',
element: document.querySelector('.menu-one'),
}),
BubbleMenu.configure({
pluginKey: 'bubbleMenuTwo',
element: document.querySelector('.menu-two'),
}),
],
})
shouldShow 一个控制菜单是否显示的回调函数。
BubbleMenu.configure({
shouldShow: ({ editor, view, state, oldState, from, to }) => {
//如果是图片或链接才显示菜单
return editor.isActive('image') || editor.isActive('link')
},
})
import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'
new Editor({
extensions: [
BubbleMenu.configure({
element: document.querySelector('.menu'),
}),
],
})
Vue 例子
React 例子
React CSS
<template>
<div>
<div>
<input type="checkbox" :checked="isEditable" @change="() => isEditable = !isEditable">
Editable
</div>
<bubble-menu
:editor="editor"
:tippy-options="{ duration: 100 }"
v-if="editor"
>
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
bold
</button>
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
italic
</button>
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
strike
</button>
</bubble-menu>
<editor-content :editor="editor" />
</div>
</template>
<script>
import StarterKit from '@tiptap/starter-kit'
import { BubbleMenu, Editor, EditorContent } from '@tiptap/vue-3'
export default {
components: {
EditorContent,
BubbleMenu,
},
data() {
return {
editor: null,
isEditable: true,
}
},
watch: {
isEditable(value) {
this.editor.setEditable(value)
},
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
],
content: `
<p>
IT小书童 - 为程序员提供优质教程和文档,你选择几个文字试试看 www.itxst.com
</p>
`,
})
},
beforeUnmount() {
this.editor.destroy()
},
}
</script>
<style>
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
input[type="checkbox"] {
margin-right: 4px;
}
</style>
import './styles.scss'
import {
BubbleMenu, EditorContent, useEditor,
} from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import React, { useEffect } from 'react'
export default () => {
const editor = useEditor({
extensions: [
StarterKit,
],
content: `
<p>
Hey, try to select some text here. There will popup a menu for selecting some inline styles. Remember: you have full control about content and styling of this menu.
</p>
`,
})
const [isEditable, setIsEditable] = React.useState(true)
useEffect(() => {
if (editor) {
editor.setEditable(isEditable)
}
}, [isEditable, editor])
return (
<>
<div>
<input type="checkbox" checked={isEditable} onChange={() => setIsEditable(!isEditable)} />
Editable
</div>
{editor && <BubbleMenu editor={editor} tippyOptions={{ duration: 100 }}>
<button
onClick={() => editor.chain().focus().toggleBold().run()}
className={editor.isActive('bold') ? 'is-active' : ''}
>
bold
</button>
<button
onClick={() => editor.chain().focus().toggleItalic().run()}
className={editor.isActive('italic') ? 'is-active' : ''}
>
italic
</button>
<button
onClick={() => editor.chain().focus().toggleStrike().run()}
className={editor.isActive('strike') ? 'is-active' : ''}
>
strike
</button>
</BubbleMenu>}
<EditorContent editor={editor} />
</>
)
}
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
input[type="checkbox"] {
margin-right: 8px;
}