184 lines
3.8 KiB
Vue
184 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import type { PropType } from 'vue'
|
|
import { EditorContent, type Editor } from '@tiptap/vue-3'
|
|
|
|
defineProps({
|
|
editor: {
|
|
type: Object as PropType<Editor | null>,
|
|
default: null,
|
|
},
|
|
isBoldActive: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
isItalicActive: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
isUnderlineActive: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
isBulletListActive: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
isOrderedListActive: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
isLinkActive: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
})
|
|
|
|
defineEmits<{
|
|
bold: []
|
|
italic: []
|
|
underline: []
|
|
bulletList: []
|
|
orderedList: []
|
|
link: []
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<v-toolbar density="compact" elevation="0" class="editor-toolbar">
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
:class="{ 'v-btn--active': isBoldActive }"
|
|
@click="$emit('bold')"
|
|
>
|
|
<v-icon>mdi-format-bold</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Bold</v-tooltip>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
:class="{ 'v-btn--active': isItalicActive }"
|
|
@click="$emit('italic')"
|
|
>
|
|
<v-icon>mdi-format-italic</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Italic</v-tooltip>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
:class="{ 'v-btn--active': isUnderlineActive }"
|
|
@click="$emit('underline')"
|
|
>
|
|
<v-icon>mdi-format-underline</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Underline</v-tooltip>
|
|
</v-btn>
|
|
|
|
<v-divider vertical class="mx-2" />
|
|
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
:class="{ 'v-btn--active': isBulletListActive }"
|
|
@click="$emit('bulletList')"
|
|
>
|
|
<v-icon>mdi-format-list-bulleted</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Bullet List</v-tooltip>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
:class="{ 'v-btn--active': isOrderedListActive }"
|
|
@click="$emit('orderedList')"
|
|
>
|
|
<v-icon>mdi-format-list-numbered</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Numbered List</v-tooltip>
|
|
</v-btn>
|
|
|
|
<v-divider vertical class="mx-2" />
|
|
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
:class="{ 'v-btn--active': isLinkActive }"
|
|
@click="$emit('link')"
|
|
>
|
|
<v-icon>mdi-link</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Link</v-tooltip>
|
|
</v-btn>
|
|
|
|
<v-spacer />
|
|
|
|
<v-btn icon size="small">
|
|
<v-icon>mdi-paperclip</v-icon>
|
|
<v-tooltip activator="parent" location="bottom">Attach Files</v-tooltip>
|
|
</v-btn>
|
|
</v-toolbar>
|
|
|
|
<v-divider />
|
|
|
|
<div class="editor-container">
|
|
<EditorContent :editor="editor" />
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.editor-toolbar {
|
|
flex-shrink: 0;
|
|
border-bottom: 1px solid rgb(var(--v-border-color));
|
|
}
|
|
|
|
.editor-container {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
background-color: rgb(var(--v-theme-background));
|
|
}
|
|
|
|
.v-btn--active {
|
|
background-color: rgba(var(--v-theme-primary), 0.12);
|
|
color: rgb(var(--v-theme-primary));
|
|
}
|
|
|
|
:deep(.tiptap-editor) {
|
|
outline: none;
|
|
min-height: 300px;
|
|
|
|
p.is-editor-empty:first-child::before {
|
|
color: rgb(var(--v-theme-on-surface-variant));
|
|
content: attr(data-placeholder);
|
|
float: left;
|
|
height: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
line-height: 1.3;
|
|
margin-top: 1em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
p {
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
ul, ol {
|
|
padding-left: 1.5em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
blockquote {
|
|
border-left: 3px solid rgb(var(--v-border-color));
|
|
padding-left: 1em;
|
|
margin-left: 0;
|
|
margin-bottom: 0.5em;
|
|
color: rgb(var(--v-theme-on-surface-variant));
|
|
}
|
|
|
|
a {
|
|
color: rgb(var(--v-theme-primary));
|
|
text-decoration: underline;
|
|
}
|
|
}
|
|
</style> |