104 lines
4.7 KiB
Vue
104 lines
4.7 KiB
Vue
<script setup lang="ts">
|
|
import { Editor, } from '@tiptap/vue-3'
|
|
import { computed, onMounted, ref } from 'vue';
|
|
import { ButtonGroup, ButtonGroupSeparator } from './ui/button-group';
|
|
import { Button } from './ui/crm-button';
|
|
import { Bold, Code2, Heading, Heading1, Heading2, Heading3, Heading4, Heading5, Heading6, Italic, List, ListOrdered, Pilcrow, Redo2, Strikethrough, Undo2 } from 'lucide-vue-next';
|
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, DropdownMenuSeparator } from '@/components/ui/dropdown-menu'
|
|
|
|
const props = defineProps<{
|
|
editor: Editor | undefined
|
|
}>()
|
|
|
|
const position = ref({ top: 0, left: 0 })
|
|
|
|
onMounted(() => {
|
|
position.value.left = props.editor?.options.element.getBoundingClientRect().x
|
|
position.value.top = props.editor?.options.element.getBoundingClientRect().y
|
|
})
|
|
|
|
const positionStyle = computed(() => {
|
|
return 'top: calc(' + position.value.top + 'px - var(--spacing) * 9); ' +
|
|
'left: ' + position.value.left + 'px;'
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<ButtonGroup
|
|
class="editor-menu z-50 border shadow rounded-md overflow-clip bg-background pointer-events-auto"
|
|
:style="positionStyle">
|
|
<Button @click="editor?.chain().focus().undo().run()" :disabled="!editor?.can().undo()" size="sm"
|
|
variant="ghost">
|
|
<Undo2 />
|
|
</Button>
|
|
<Button @click="editor?.chain().focus().redo().run()" :disabled="!editor?.can().redo()" size="sm"
|
|
variant="ghost">
|
|
<redo2 />
|
|
</Button>
|
|
|
|
<ButtonGroupSeparator />
|
|
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger as-child>
|
|
<Button size="sm" variant="ghost">
|
|
<heading />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent>
|
|
<DropdownMenuItem @click="editor?.chain().focus().clearNodes().run()" size="sm">
|
|
<pilcrow /> Absatz
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem @click="editor?.chain().focus().toggleHeading({ level: 1 }).run()">
|
|
<heading1 /> Überschrift 1
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem @click="editor?.chain().focus().toggleHeading({ level: 2 }).run()">
|
|
<heading2 /> Überschrift 2
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem @click="editor?.chain().focus().toggleHeading({ level: 3 }).run()">
|
|
<heading3 /> Überschrift 3
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem @click="editor?.chain().focus().toggleHeading({ level: 4 }).run()">
|
|
<heading4 /> Überschrift 4
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem @click="editor?.chain().focus().toggleHeading({ level: 5 }).run()">
|
|
<heading5 /> Überschrift 5
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem @click="editor?.chain().focus().toggleHeading({ level: 6 }).run()">
|
|
<heading6 /> Überschrift 6
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
|
|
<dropdown-menu>
|
|
<dropdown-menu-trigger as-child>
|
|
<Button size="sm" variant="ghost">
|
|
<list />
|
|
</Button>
|
|
</dropdown-menu-trigger>
|
|
<dropdown-menu-content>
|
|
<dropdown-menu-item @click="editor?.chain().focus().toggleBulletList().run()">
|
|
<list /> Ungeordnete Liste
|
|
</dropdown-menu-item>
|
|
<dropdown-menu-item @click="editor?.chain().focus().toggleOrderedList().run()"><list-ordered />
|
|
Geordnete Liste</dropdown-menu-item>
|
|
</dropdown-menu-content>
|
|
</dropdown-menu>
|
|
|
|
<ButtonGroupSeparator />
|
|
|
|
<Button @click="editor?.chain().focus().toggleBold().run()"
|
|
:class="{ 'is-active': editor?.isActive('bold') }" size="sm" variant="ghost">
|
|
<Bold />
|
|
</Button>
|
|
<Button @click="editor?.chain().focus().toggleItalic().run()" size="sm" variant="ghost">
|
|
<Italic />
|
|
</Button>
|
|
<Button @click="editor?.chain().focus().toggleStrike().run()" size="sm" variant="ghost">
|
|
<strikethrough />
|
|
</Button>
|
|
<Button @click="editor?.chain().focus().toggleCode().run()" size="sm" variant="ghost">
|
|
<code2 />
|
|
</Button>
|
|
</ButtonGroup>
|
|
</template> |