UNPKG

tiptapify

Version:

Tiptap3 editor with Vuetify3 menu implementation

107 lines (90 loc) 2.62 kB
import { computePosition, flip, shift } from '@floating-ui/dom' import { posToDOMRect, VueRenderer } from '@tiptap/vue-3' import CommandsList from './CommandsList.vue' const updatePosition = (editor, element) => { const virtualElement = { getBoundingClientRect: () => posToDOMRect(editor.view, editor.state.selection.from, editor.state.selection.to), } computePosition(virtualElement, element, { placement: 'bottom-start', strategy: 'absolute', middleware: [shift(), flip()], }).then(({ x, y, strategy }) => { element.style.width = 'max-content' element.style.position = strategy element.style.left = `${x}px` element.style.top = `${y}px` }) } export default { items: ({ query }) => { return [ { title: 'H1', icon: 'FormatHeader1', command: ({ editor, range }) => { editor.chain().focus().deleteRange(range).setNode('heading', { level: 1 }).run() }, }, { title: 'H2', icon: 'FormatHeader2', command: ({ editor, range }) => { editor.chain().focus().deleteRange(range).setNode('heading', { level: 2 }).run() }, }, { title: 'Bold', icon: 'FormatBold', command: ({ editor, range }) => { editor.chain().focus().deleteRange(range).setMark('bold').run() }, }, { title: 'Italic', icon: 'FormatItalic', command: ({ editor, range }) => { editor.chain().focus().deleteRange(range).setMark('italic').run() }, }, ] .filter(item => item.title.toLowerCase().startsWith(query.toLowerCase())) .slice(0, 10) }, render: () => { let component return { onStart: props => { component = new VueRenderer(CommandsList, { props, editor: props.editor, }) if (!props.clientRect) { return } component.element.style.position = 'absolute' document.body.appendChild(component.element) updatePosition(props.editor, component.element) }, onUpdate(props) { component.updateProps(props) if (!props.clientRect) { return } updatePosition(props.editor, component.element) }, onKeyDown(props) { if (props.event.key === 'Escape') { component.destroy() component.element.remove() return true } return component.ref?.onKeyDown(props) }, onExit() { component.destroy() component.element.remove() }, } }, }