it-tools/src/tools/html-wysiwyg-editor/editor/menu-bar.vue

168 lines
4.1 KiB
Vue
Raw Normal View History

2023-03-26 19:04:42 +02:00
<script setup lang="ts">
import type { Editor } from '@tiptap/vue-3';
import {
IconArrowBack,
IconArrowForwardUp,
IconBlockquote,
IconBold,
IconClearFormatting,
IconCode,
IconCodePlus,
IconH1,
IconH2,
IconH3,
IconH4,
IconItalic,
IconList,
IconListNumbers,
IconStrikethrough,
IconTextWrap,
} from '@tabler/icons-vue';
import type { Component } from 'vue';
2023-03-26 19:04:42 +02:00
import MenuBarItem from './menu-bar-item.vue';
const props = defineProps<{ editor: Editor }>();
const { editor } = toRefs(props);
type MenuItem =
| {
icon: Component
title: string
action: () => void
isActive?: () => boolean
type: 'button'
}
2023-03-26 19:04:42 +02:00
| { type: 'divider' };
const items: MenuItem[] = [
{
type: 'button',
icon: IconBold,
2023-03-26 19:04:42 +02:00
title: 'Bold',
action: () => editor.value.chain().focus().toggleBold().run(),
isActive: () => editor.value.isActive('bold'),
},
{
type: 'button',
icon: IconItalic,
2023-03-26 19:04:42 +02:00
title: 'Italic',
action: () => editor.value.chain().focus().toggleItalic().run(),
isActive: () => editor.value.isActive('italic'),
},
{
type: 'button',
icon: IconStrikethrough,
2023-03-26 19:04:42 +02:00
title: 'Strike',
action: () => editor.value.chain().focus().toggleStrike().run(),
isActive: () => editor.value.isActive('strike'),
},
{
type: 'button',
icon: IconCode,
2023-03-26 19:04:42 +02:00
title: 'Inline code',
action: () => editor.value.chain().focus().toggleCode().run(),
isActive: () => editor.value.isActive('code'),
},
{
type: 'divider',
},
{
type: 'button',
icon: IconH1,
2023-03-26 19:04:42 +02:00
title: 'Heading 1',
action: () => editor.value.chain().focus().toggleHeading({ level: 1 }).run(),
isActive: () => editor.value.isActive('heading', { level: 1 }),
},
{
type: 'button',
icon: IconH2,
2023-03-26 19:04:42 +02:00
title: 'Heading 2',
action: () => editor.value.chain().focus().toggleHeading({ level: 2 }).run(),
isActive: () => editor.value.isActive('heading', { level: 2 }),
},
{
type: 'button',
icon: IconH3,
2023-03-26 19:04:42 +02:00
title: 'Heading 3',
action: () => editor.value.chain().focus().toggleHeading({ level: 3 }).run(),
isActive: () => editor.value.isActive('heading', { level: 3 }),
2023-03-26 19:04:42 +02:00
},
{
type: 'button',
icon: IconH4,
2023-03-26 19:04:42 +02:00
title: 'Heading 4',
action: () => editor.value.chain().focus().toggleHeading({ level: 4 }).run(),
isActive: () => editor.value.isActive('heading', { level: 4 }),
},
{
type: 'divider',
},
{
type: 'button',
icon: IconList,
2023-03-26 19:04:42 +02:00
title: 'Bullet list',
action: () => editor.value.chain().focus().toggleBulletList().run(),
isActive: () => editor.value.isActive('bulletList'),
},
{
type: 'button',
icon: IconListNumbers,
2023-03-26 19:04:42 +02:00
title: 'Ordered list',
action: () => editor.value.chain().focus().toggleOrderedList().run(),
isActive: () => editor.value.isActive('orderedList'),
},
{
type: 'button',
icon: IconCodePlus,
2023-03-26 19:04:42 +02:00
title: 'Code block',
action: () => editor.value.chain().focus().toggleCodeBlock().run(),
isActive: () => editor.value.isActive('codeBlock'),
},
{
type: 'button',
icon: IconBlockquote,
2023-03-26 19:04:42 +02:00
title: 'Blockquote',
action: () => editor.value.chain().focus().toggleBlockquote().run(),
isActive: () => editor.value.isActive('blockquote'),
},
{
type: 'divider',
},
{
type: 'button',
icon: IconTextWrap,
2023-03-26 19:04:42 +02:00
title: 'Hard break',
action: () => editor.value.chain().focus().setHardBreak().run(),
},
{
type: 'button',
icon: IconClearFormatting,
2023-03-26 19:04:42 +02:00
title: 'Clear format',
action: () => editor.value.chain().focus().clearNodes().unsetAllMarks().run(),
},
{
type: 'button',
icon: IconArrowBack,
2023-03-26 19:04:42 +02:00
title: 'Undo',
action: () => editor.value.chain().focus().undo().run(),
},
{
type: 'button',
icon: IconArrowForwardUp,
2023-03-26 19:04:42 +02:00
title: 'Redo',
action: () => editor.value.chain().focus().redo().run(),
},
];
</script>
<template>
<div flex items-center>
<template v-for="(item, index) in items">
<n-divider v-if="item.type === 'divider'" :key="`divider${index}`" vertical />
<MenuBarItem v-else-if="item.type === 'button'" :key="index" v-bind="item" />
</template>
</div>
</template>