|
|
<script setup> |
|
|
import { reactive, ref } from 'vue'; |
|
|
import { FloatingMenu } from '@tiptap/vue-3' |
|
|
const props = defineProps({ |
|
|
editor: { |
|
|
type: Object, |
|
|
required: true, |
|
|
} |
|
|
}); |
|
|
const editor = reactive(props.editor); |
|
|
|
|
|
const addImage = () => { |
|
|
const url = window.prompt('Enter image URL') |
|
|
if (url) { |
|
|
editor |
|
|
.chain() |
|
|
.focus() |
|
|
.setImage({ src: url }) |
|
|
.run() |
|
|
} |
|
|
} |
|
|
|
|
|
const addTable = () => { |
|
|
editor |
|
|
.chain() |
|
|
.focus() |
|
|
.insertTable({ rows: 3, cols: 3, withHeaderRow: true }) |
|
|
.run() |
|
|
} |
|
|
</script> |
|
|
<template> |
|
|
<floating-menu |
|
|
v-if="editor" |
|
|
:editor="editor" |
|
|
:tippy-options="{ duration: 100, placement: 'bottom-start' }" |
|
|
class="z-50 bg-white border border-gray-200 rounded-lg shadow-lg p-2 flex flex-col space-y-1 min-w-[200px]" |
|
|
> |
|
|
<button |
|
|
@click="editor.chain().focus().setParagraph().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('paragraph') }" |
|
|
> |
|
|
<span class="mr-2">¶</span> |
|
|
<span>Paragraph</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('heading', { level: 1 }) }" |
|
|
> |
|
|
<span class="mr-2 font-bold text-lg">H1</span> |
|
|
<span>Heading 1</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('heading', { level: 2 }) }" |
|
|
> |
|
|
<span class="mr-2 font-bold">H2</span> |
|
|
<span>Heading 2</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('heading', { level: 3 }) }" |
|
|
> |
|
|
<span class="mr-2 font-bold text-sm">H3</span> |
|
|
<span>Heading 3</span> |
|
|
</button> |
|
|
|
|
|
<div class="h-px bg-gray-200 my-1"></div> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleBulletList().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('bulletList') }" |
|
|
> |
|
|
<span class="mr-2">•</span> |
|
|
<span>Bullet List</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleOrderedList().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('orderedList') }" |
|
|
> |
|
|
<span class="mr-2">1.</span> |
|
|
<span>Numbered List</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleTaskList().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('taskList') }" |
|
|
> |
|
|
<span class="mr-2">☑️</span> |
|
|
<span>Task List</span> |
|
|
</button> |
|
|
|
|
|
<div class="h-px bg-gray-200 my-1"></div> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleBlockquote().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('blockquote') }" |
|
|
> |
|
|
<span class="mr-2">"</span> |
|
|
<span>Quote</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().toggleCodeBlock().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
:class="{ 'bg-gray-100': editor.isActive('codeBlock') }" |
|
|
> |
|
|
<span class="mr-2">{"}</span> |
|
|
<span>Code Block</span> |
|
|
</button> |
|
|
|
|
|
<div class="h-px bg-gray-200 my-1"></div> |
|
|
|
|
|
<button |
|
|
@click="editor.chain().focus().setHorizontalRule().run()" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
> |
|
|
<span class="mr-2">—</span> |
|
|
<span>Horizontal Rule</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="addTable" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
> |
|
|
<span class="mr-2">⊞</span> |
|
|
<span>Table</span> |
|
|
</button> |
|
|
|
|
|
<button |
|
|
@click="addImage" |
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-gray-100 text-left text-sm" |
|
|
> |
|
|
<span class="mr-2">🖼️</span> |
|
|
<span>Image</span> |
|
|
</button> |
|
|
</floating-menu> |
|
|
</template> |