add more advance composer feature

This commit is contained in:
grimhilt
2023-04-16 01:19:58 +02:00
parent 4d3fbe292e
commit 318748c984
14 changed files with 197 additions and 117 deletions

View File

@@ -1,27 +1,29 @@
<script setup>
import { inject, ref } from "vue";
import store from "@/store/store";
import { BubbleMenu, useEditor, EditorContent, FloatingMenu } from "@tiptap/vue-3";
import imapAPI from "@/services/imapAPI";
import Underline from "@tiptap/extension-underline";
import Bold from "@tiptap/extension-bold";
import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph";
import Text from "@tiptap/extension-text";
import Highlight from "@tiptap/extension-highlight";
import Italic from "@tiptap/extension-italic";
import Link from "@tiptap/extension-link";
import Strike from "@tiptap/extension-strike";
import History from "@tiptap/extension-history";
import TextAlign from "@tiptap/extension-text-align";
import OrderedList from "@tiptap/extension-ordered-list";
import bulletList from "@tiptap/extension-bullet-list";
import HardBreak from "@tiptap/extension-hard-break";
import heading from "@tiptap/extension-heading";
import Image from "@tiptap/extension-image";
import TaskList from "@tiptap/extension-task-list";
import SvgLoader from "@/components/utils/SvgLoader.vue";
import { BubbleMenu, useEditor, EditorContent } from "@tiptap/vue-3";
import Document from "@tiptap/extension-document";
import Text from "@tiptap/extension-text";
import Paragraph from "@tiptap/extension-paragraph";
import HardBreak from "@tiptap/extension-hard-break";
import History from "@tiptap/extension-history";
import Bold from "@tiptap/extension-bold";
import Italic from "@tiptap/extension-italic";
import Strike from "@tiptap/extension-strike";
import Underline from "@tiptap/extension-underline";
import Highlight from "@tiptap/extension-highlight";
import Link from "@tiptap/extension-link";
import Heading from "@tiptap/extension-heading";
import Image from "@tiptap/extension-image";
import TextAlign from "@tiptap/extension-text-align";
import ListItem from "@tiptap/extension-list-item";
import OrderedList from "@tiptap/extension-ordered-list";
import BulletList from "@tiptap/extension-bullet-list";
// todo task list
// todo style link
// todo link and drop cursor
// todo mentions
@@ -37,18 +39,25 @@ const editor = useEditor({
depth: 10,
}),
// marks
Bold,
Italic,
Strike,
Underline,
Link,
Bold,
Strike,
Italic,
// nodes
Highlight.configure({
multicolor: true,
}),
Heading.configure({
level: [2, 3, 4],
}),
Image,
TextAlign.configure({
types: ["heading", "paragraph"],
}),
ListItem,
OrderedList,
BulletList,
],
content: `
<p>
@@ -84,63 +93,126 @@ function sendMessage() {
</script>
<!-- todo tooltip -->
<template>
<div class="main">
<div v-if="editor">
<bubble-menu class="bubble-menu" :tippy-options="{ duration: 100 }" :editor="editor">
<div v-if="editor">
<div id="options" v-if="showOptions">
<span class="category">
<SvgLoader
svg="bold"
@click="editor.chain().focus().toggleBold().run()"
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
/>
<SvgLoader
svg="italic"
@click="editor.chain().focus().toggleItalic().run()"
:class="[{ 'is-active': editor.isActive('italic') }, 'editorOption']"
v-tooltip="'Italic'"
/>
<SvgLoader
svg="strikethrough"
@click="editor.chain().focus().toggleStrike().run()"
:class="[{ 'is-active': editor.isActive('strike') }, 'editorOption']"
/>
<SvgLoader
svg="underline"
@click="editor.chain().focus().toggleUnderline().run()"
:class="[{ 'is-active': editor.isActive('underline') }, 'editorOption']"
/>
<SvgLoader
svg="font-color"
@click="editor.commands.toggleHighlight({ color: '#ffcc00' })"
:class="[{ 'is-active': editor.isActive('highlight') }, 'editorOption']"
/>
</bubble-menu>
<floating-menu class="floating-menu" :tippy-options="{ duration: 100 }" :editor="editor">
<button
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
>
H1
</button>
<button
svg="h-2"
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
>
H2
</button>
<button
:class="[{ 'is-active': editor.isActive({ level: 2 }) }, 'editorOption']"
/>
<SvgLoader
svg="h-3"
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
:class="[{ 'is-active': editor.isActive({ level: 3 }) }, 'editorOption']"
/>
<SvgLoader
svg="h-4"
@click="editor.chain().focus().toggleHeading({ level: 4 }).run()"
:class="[{ 'is-active': editor.isActive({ level: 4 }) }, 'editorOption']"
/>
</span>
<!-- <SvgLoader
svg="link"
@click="editor.chain().focus().toggleBold().run()"
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
/> -->
<span class="category">
<SvgLoader
svg="list-ordered"
@click="editor.chain().focus().toggleOrderedList().run()"
:class="[{ 'is-active': editor.isActive('orderedList') }, 'editorOption']"
/>
<SvgLoader
svg="list-unordered"
@click="editor.chain().focus().toggleBulletList().run()"
:class="{ 'is-active': editor.isActive('bulletList') }"
>
Bullet List
</button>
</floating-menu>
</div>
:class="[{ 'is-active': editor.isActive('bulletList') }, 'editorOption']"
/>
</span>
<span class="category">
<SvgLoader
svg="align-left"
@click="editor.chain().focus().setTextAlign('left').run()"
:class="[{ 'is-active': editor.isActive({ textAlign: 'left' }) }, 'editorOption']"
/>
<SvgLoader
svg="align-center"
@click="editor.chain().focus().setTextAlign('center').run()"
:class="[{ 'is-active': editor.isActive({ textAlign: 'center' }) }, 'editorOption']"
/>
<SvgLoader
svg="align-right"
@click="editor.chain().focus().setTextAlign('right').run()"
:class="[{ 'is-active': editor.isActive({ textAlign: 'right' }) }, 'editorOption']"
/>
<SvgLoader
svg="align-justify"
@click="editor.chain().focus().setTextAlign('justify').run()"
:class="[{ 'is-active': editor.isActive({ textAlign: 'justify' }) }, 'editorOption']"
/>
</span>
<div class="editor">
<div class="options" v-if="showOptions">heruipaghruie</div>
<editor-content class="editorContent" :editor="editor" aria-expanded="false" />
<!-- <SvgLoader
svg="font-color"
@click="editor.chain().focus().toggleBold().run()"
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
/>
<SvgLoader
svg="paint-fill"
@click="editor.chain().focus().toggleBold().run()"
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
/> -->
<span class="category">
<SvgLoader
svg="indent-increase"
@click="!$event.disabled ? editor.chain().focus().sinkListItem('listItem').run() : ''"
:class="[{ disabled: !editor.can().sinkListItem('listItem') }, 'editorOption']"
:isDisabled="!editor.can().sinkListItem('listItem')"
/>
<SvgLoader
svg="indent-decrease"
@click="!$event.disabled ? editor.chain().focus().liftListItem('listItem').run() : ''"
:class="[{ disabled: !editor.can().liftListItem('listItem') }, 'editorOption']"
:isDisabled="!editor.can().liftListItem('listItem')"
/>
</span>
<!-- <SvgLoader
svg="image-add-line"
@click="editor.chain().focus().toggleBold().run()"
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
/> -->
</div>
<bubble-menu class="bubble-menu" :tippy-options="{ duration: 100 }" :editor="editor">
<SvgLoader
svg="bold"
@click="editor.chain().focus().toggleBold().run()"
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
/>
<SvgLoader
svg="italic"
@click="editor.chain().focus().toggleItalic().run()"
:class="[{ 'is-active': editor.isActive('italic') }, 'editorOption']"
v-tooltip="'Italic'"
/>
<SvgLoader
svg="strikethrough"
@click="editor.chain().focus().toggleStrike().run()"
:class="[{ 'is-active': editor.isActive('strike') }, 'editorOption']"
/>
<SvgLoader
svg="underline"
@click="editor.chain().focus().toggleUnderline().run()"
:class="[{ 'is-active': editor.isActive('underline') }, 'editorOption']"
/>
<SvgLoader
svg="font-color"
@click="editor.commands.toggleHighlight({ color: '#ffcc00' })"
:class="[{ 'is-active': editor.isActive('highlight') }, 'editorOption']"
/>
</bubble-menu>
</div>
<div class="main">
<editor-content class="editor" :editor="editor" aria-expanded="false" />
<div class="actions">
<SvgLoader class="sendMessage" svg="send-plane-line" @click="sendMessage()" />
<SvgLoader
@@ -152,15 +224,9 @@ function sendMessage() {
</div>
</template>
<style lang="scss">
.ProseMirror {
&:focus {
outline: none;
}
p {
margin: 0;
}
<style>
.ProseMirror:focus {
outline: none;
}
</style>
@@ -168,52 +234,54 @@ function sendMessage() {
.main {
display: flex;
flex-direction: row;
padding: 10px;
padding: 0 10px 10px 10px;
overflow: auto;
}
.editor {
display: flex;
flex-direction: column;
background-color: var(--secondary-background);
flex: 1;
margin-right: 10px;
}
.options {
background-color: blue;
}
.editorContent {
flex: 1;
background-color: var(--secondary-background);
border-radius: 10px;
padding: 0 10px;
overflow: auto;
}
.bubble-menu {
.bubble-menu,
#options,
.category {
display: flex;
flex-direction: row;
gap: 2px;
background-color: var(--primary-background);
border: 1px solid var(--border-color);
}
#options {
margin: 2px 0 4px 11px;
gap: 6px;
}
.bubble-menu,
.category {
outline: 1px solid var(--border-color);
border-radius: 8px;
padding: 2px;
}
.editorOption {
border-radius: 6px;
cursor: pointer;
.editorOption {
border-radius: 6px;
cursor: pointer;
&:hover,
&.is-active {
background-color: var(--selected);
}
::v-deep img {
filter: var(--svg-primary-text);
padding: 1px;
}
&:hover,
&.is-active {
background-color: var(--selected);
}
}
.disabled {
opacity: 0.5;
}
.actions {
display: flex;
flex-direction: column;
@@ -225,7 +293,6 @@ function sendMessage() {
border-radius: 6px;
::v-deep img {
filter: var(--svg-primary-text);
padding: 3px;
cursor: pointer;
}

View File

@@ -3,15 +3,22 @@ import { defineProps } from "vue";
const props = defineProps({
svg: { type: String, required: true },
isDisabled: Boolean,
});
const pathSvg = () => require(`@/assets/svg/${props.svg}.svg`);
console.log(props.isDisabled);
</script>
<template>
<div>
<img class="it-has-a-tooltip" :src="pathSvg()" />
<img :disabled="props.isDisabled" :src="pathSvg()" />
</div>
</template>
<style scoped></style>
<style scoped>
img {
filter: var(--svg-primary-text);
padding: 1px;
}
</style>