tiptapify 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/tiptapify.css +1 -1
- package/dist/tiptapify.mjs +21133 -19765
- package/dist/tiptapify.umd.js +37 -38
- package/package.json +43 -43
- package/src/components/Tiptapify.vue +2 -2
- package/src/components/Toolbar/GroupBtn.vue +2 -6
- package/src/components/Toolbar/GroupDropdown.vue +4 -8
- package/src/components/Toolbar/Index.vue +5 -4
- package/src/components/Toolbar/Items.vue +2 -2
- package/src/components/Toolbar/Toggle.vue +2 -2
- package/src/components/Toolbar/items.ts +20 -20
- package/src/components/UI/Dialog.vue +141 -0
- package/src/components/editorExtensions.ts +1 -1
- package/src/{components/Toolbar/items/actions.ts → composables/Toolbar/useActionsItems.ts} +6 -3
- package/src/{components/Toolbar/items/alignment.ts → composables/Toolbar/useAlignmentItems.ts} +12 -9
- package/src/{components/Toolbar/items/formatExtra.ts → composables/Toolbar/useFormatExtraItems.ts} +10 -7
- package/src/{components/Toolbar/items/format.ts → composables/Toolbar/useFormatItems.ts} +20 -17
- package/src/{components/Toolbar/items/list.ts → composables/Toolbar/useListItems.ts} +14 -11
- package/src/{components/Toolbar/items/media.ts → composables/Toolbar/useMediaItems.ts} +22 -20
- package/src/{components/Toolbar/items/misc.ts → composables/Toolbar/useMiscItems.ts} +9 -6
- package/src/composables/Toolbar/useStyleItems.ts +231 -0
- package/src/{components/Toolbar/fonts.ts → constants/style.ts} +21 -0
- package/src/extensions/components/FontFamily.vue +82 -0
- package/src/extensions/components/FontSize.vue +83 -0
- package/src/extensions/components/ImageDialog.vue +17 -29
- package/src/extensions/components/LineHeight.vue +82 -0
- package/src/extensions/components/LinkDialog.vue +75 -44
- package/src/extensions/components/PreviewDialog.vue +8 -16
- package/src/extensions/components/ShowSourceDialog.vue +17 -18
- package/src/extensions/components/StyleColor.vue +68 -15
- package/src/extensions/components/TableBuilder.vue +3 -6
- package/src/extensions/link.ts +8 -0
- package/src/extensions/slash-commands.ts +1 -1
- package/src/i18n/index.ts +0 -1
- package/src/i18n/locales/ch.json +119 -0
- package/src/i18n/locales/cz.json +119 -0
- package/src/i18n/locales/de.json +83 -76
- package/src/i18n/locales/en.json +82 -75
- package/src/i18n/locales/es.json +80 -73
- package/src/i18n/locales/fr.json +81 -73
- package/src/i18n/locales/it.json +80 -73
- package/src/i18n/locales/la.json +119 -0
- package/src/i18n/locales/lt.json +119 -0
- package/src/i18n/locales/nl.json +119 -0
- package/src/i18n/locales/pl.json +80 -74
- package/src/i18n/locales/pt.json +119 -0
- package/src/i18n/locales/ru.json +78 -71
- package/src/i18n/locales/se.json +119 -0
- package/src/i18n/locales/ua.json +79 -72
- package/src/components/Toolbar/items/style.ts +0 -187
- /package/src/{components → extensions/components}/CodeBlockComponent.vue +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as mdi from "@mdi/js";
|
|
2
2
|
import { Editor } from "@tiptap/vue-3";
|
|
3
3
|
import { computed } from "vue";
|
|
4
|
+
import { useI18n } from "vue-i18n";
|
|
5
|
+
|
|
6
|
+
export function useFormatItems(editor: Editor) {
|
|
7
|
+
const { t } = useI18n();
|
|
4
8
|
|
|
5
|
-
export function getFormatItems(editor: Editor) {
|
|
6
9
|
return {
|
|
7
10
|
bold: {
|
|
8
11
|
name: 'bold',
|
|
9
|
-
tooltip: 'format.bold',
|
|
12
|
+
tooltip: computed(() => t('format.bold')),
|
|
10
13
|
icon: mdi.mdiFormatBold,
|
|
11
14
|
enabled: true,
|
|
12
15
|
props: {
|
|
@@ -19,7 +22,7 @@ export function getFormatItems(editor: Editor) {
|
|
|
19
22
|
},
|
|
20
23
|
italic: {
|
|
21
24
|
name: 'italic',
|
|
22
|
-
tooltip: 'format.italic',
|
|
25
|
+
tooltip: computed(() => t('format.italic')),
|
|
23
26
|
icon: mdi.mdiFormatItalic,
|
|
24
27
|
enabled: true,
|
|
25
28
|
props: {
|
|
@@ -30,22 +33,9 @@ export function getFormatItems(editor: Editor) {
|
|
|
30
33
|
click: () => editor.chain().focus().toggleItalic().run()
|
|
31
34
|
}
|
|
32
35
|
},
|
|
33
|
-
strike: {
|
|
34
|
-
name: 'strike',
|
|
35
|
-
tooltip: 'format.strike',
|
|
36
|
-
icon: mdi.mdiFormatStrikethroughVariant,
|
|
37
|
-
enabled: true,
|
|
38
|
-
props: {
|
|
39
|
-
disabled: computed(() => !editor.can().chain().focus().toggleStrike().run()),
|
|
40
|
-
color: computed(() => editor.isActive('strike') ? 'primary' : ''),
|
|
41
|
-
},
|
|
42
|
-
attrs: {
|
|
43
|
-
click: () => editor.chain().focus().toggleStrike().run()
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
36
|
underline: {
|
|
47
37
|
name: 'underline',
|
|
48
|
-
tooltip: 'format.underline',
|
|
38
|
+
tooltip: computed(() => t('format.underline')),
|
|
49
39
|
icon: mdi.mdiFormatUnderline,
|
|
50
40
|
enabled: true,
|
|
51
41
|
props: {
|
|
@@ -55,6 +45,19 @@ export function getFormatItems(editor: Editor) {
|
|
|
55
45
|
attrs: {
|
|
56
46
|
click: () => editor.chain().focus().toggleUnderline().run()
|
|
57
47
|
}
|
|
48
|
+
},
|
|
49
|
+
strike: {
|
|
50
|
+
name: 'strike',
|
|
51
|
+
tooltip: computed(() => t('format.strike')),
|
|
52
|
+
icon: mdi.mdiFormatStrikethroughVariant,
|
|
53
|
+
enabled: true,
|
|
54
|
+
props: {
|
|
55
|
+
disabled: computed(() => !editor.can().chain().focus().toggleStrike().run()),
|
|
56
|
+
color: computed(() => editor.isActive('strike') ? 'primary' : ''),
|
|
57
|
+
},
|
|
58
|
+
attrs: {
|
|
59
|
+
click: () => editor.chain().focus().toggleStrike().run()
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as mdi from "@mdi/js";
|
|
2
2
|
import { Editor } from "@tiptap/vue-3";
|
|
3
3
|
import { computed } from "vue";
|
|
4
|
+
import { useI18n } from "vue-i18n";
|
|
5
|
+
|
|
6
|
+
export function useListItems(editor: Editor) {
|
|
7
|
+
const { t } = useI18n();
|
|
4
8
|
|
|
5
|
-
export function getListItems(editor: Editor) {
|
|
6
9
|
return {
|
|
7
10
|
listBullet: {
|
|
8
|
-
name: 'lists.bullet',
|
|
9
|
-
tooltip: 'lists.bullet',
|
|
11
|
+
name: computed(() => t('lists.bullet')),
|
|
12
|
+
tooltip: computed(() => t('lists.bullet')),
|
|
10
13
|
icon: mdi.mdiFormatListBulleted,
|
|
11
14
|
enabled: true,
|
|
12
15
|
props: {
|
|
@@ -17,8 +20,8 @@ export function getListItems(editor: Editor) {
|
|
|
17
20
|
}
|
|
18
21
|
},
|
|
19
22
|
listNumbered: {
|
|
20
|
-
name: 'lists.numbered',
|
|
21
|
-
tooltip: 'lists.numbered',
|
|
23
|
+
name: computed(() => t('lists.numbered')),
|
|
24
|
+
tooltip: computed(() => t('lists.numbered')),
|
|
22
25
|
icon: mdi.mdiFormatListNumbered,
|
|
23
26
|
enabled: true,
|
|
24
27
|
props: {
|
|
@@ -29,8 +32,8 @@ export function getListItems(editor: Editor) {
|
|
|
29
32
|
}
|
|
30
33
|
},
|
|
31
34
|
listTask: {
|
|
32
|
-
name: 'lists.task',
|
|
33
|
-
tooltip: 'lists.task',
|
|
35
|
+
name: computed(() => t('lists.task')),
|
|
36
|
+
tooltip: computed(() => t('lists.task')),
|
|
34
37
|
icon: mdi.mdiFormatListChecks,
|
|
35
38
|
enabled: true,
|
|
36
39
|
props: {
|
|
@@ -41,8 +44,8 @@ export function getListItems(editor: Editor) {
|
|
|
41
44
|
}
|
|
42
45
|
},
|
|
43
46
|
listIndent: {
|
|
44
|
-
name: 'lists.indent',
|
|
45
|
-
tooltip: 'lists.indent',
|
|
47
|
+
name: computed(() => t('lists.indent')),
|
|
48
|
+
tooltip: computed(() => t('lists.indent')),
|
|
46
49
|
icon: mdi.mdiFormatIndentIncrease,
|
|
47
50
|
enabled: true,
|
|
48
51
|
props: {
|
|
@@ -54,8 +57,8 @@ export function getListItems(editor: Editor) {
|
|
|
54
57
|
}
|
|
55
58
|
},
|
|
56
59
|
listOutdent: {
|
|
57
|
-
name: 'lists.outdent',
|
|
58
|
-
tooltip: 'lists.outdent',
|
|
60
|
+
name: computed(() => t('lists.outdent')),
|
|
61
|
+
tooltip: computed(() => t('lists.outdent')),
|
|
59
62
|
icon: mdi.mdiFormatIndentDecrease,
|
|
60
63
|
enabled: true,
|
|
61
64
|
props: {
|
|
@@ -2,16 +2,18 @@ import * as mdi from "@mdi/js";
|
|
|
2
2
|
import { Editor } from "@tiptap/vue-3";
|
|
3
3
|
import TableBuilder from "@tiptapify/extensions/components/TableBuilder.vue";
|
|
4
4
|
import { computed, markRaw } from "vue";
|
|
5
|
+
import { useI18n } from "vue-i18n";
|
|
5
6
|
|
|
6
|
-
export function
|
|
7
|
+
export function useMediaItems(editor: Editor) {
|
|
8
|
+
const { t } = useI18n();
|
|
7
9
|
return {
|
|
8
10
|
link: {
|
|
9
|
-
name: 'media.link',
|
|
10
|
-
tooltip: 'media.link',
|
|
11
|
-
icon: computed(() => editor.isActive('
|
|
11
|
+
name: computed(() => t('media.link')),
|
|
12
|
+
tooltip: computed(() => t('media.link')),
|
|
13
|
+
icon: computed(() => editor.isActive('tiptapifyLink') ? mdi.mdiLinkOff : mdi.mdiLink),
|
|
12
14
|
enabled: true,
|
|
13
15
|
props: {
|
|
14
|
-
color: computed(() => editor.isActive('
|
|
16
|
+
color: computed(() => editor.isActive('tiptapifyLink') ? 'primary' : ''),
|
|
15
17
|
disabled: computed(() => editor.isActive('code') || editor.isActive('codeBlock')),
|
|
16
18
|
},
|
|
17
19
|
attrs: {
|
|
@@ -19,8 +21,8 @@ export function getMediaItems(editor: Editor) {
|
|
|
19
21
|
}
|
|
20
22
|
},
|
|
21
23
|
image: {
|
|
22
|
-
name: 'media.image',
|
|
23
|
-
tooltip: 'media.image',
|
|
24
|
+
name: computed(() => t('media.image')),
|
|
25
|
+
tooltip: computed(() => t('media.image')),
|
|
24
26
|
icon: mdi.mdiImage,
|
|
25
27
|
enabled: true,
|
|
26
28
|
props: {
|
|
@@ -33,7 +35,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
33
35
|
},
|
|
34
36
|
table: {
|
|
35
37
|
name: 'tables',
|
|
36
|
-
tooltip: 'media.tables.table',
|
|
38
|
+
tooltip: computed(() => t('media.tables.table')),
|
|
37
39
|
icon: mdi.mdiTable,
|
|
38
40
|
modelValue: false,
|
|
39
41
|
enabled: true,
|
|
@@ -44,7 +46,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
44
46
|
children: [
|
|
45
47
|
{
|
|
46
48
|
name: 'insert table',
|
|
47
|
-
tooltip: 'media.tables.insertTable',
|
|
49
|
+
tooltip: computed(() => t('media.tables.insertTable')),
|
|
48
50
|
icon: mdi.mdiTablePlus,
|
|
49
51
|
enabled: true,
|
|
50
52
|
props: {
|
|
@@ -59,7 +61,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
59
61
|
},
|
|
60
62
|
{
|
|
61
63
|
name: 'delete table',
|
|
62
|
-
tooltip: 'media.tables.deleteTable',
|
|
64
|
+
tooltip: computed(() => t('media.tables.deleteTable')),
|
|
63
65
|
icon: mdi.mdiTableMinus,
|
|
64
66
|
enabled: true,
|
|
65
67
|
props: {
|
|
@@ -71,7 +73,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
71
73
|
},
|
|
72
74
|
{
|
|
73
75
|
name: 'table row',
|
|
74
|
-
tooltip: 'media.tables.row',
|
|
76
|
+
tooltip: computed(() => t('media.tables.row')),
|
|
75
77
|
icon: mdi.mdiTableRow,
|
|
76
78
|
enabled: true,
|
|
77
79
|
props: {
|
|
@@ -89,7 +91,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
89
91
|
children: [
|
|
90
92
|
{
|
|
91
93
|
name: 'insert row before',
|
|
92
|
-
tooltip: 'media.tables.insertRowBefore',
|
|
94
|
+
tooltip: computed(() => t('media.tables.insertRowBefore')),
|
|
93
95
|
icon: mdi.mdiTableRowPlusBefore,
|
|
94
96
|
enabled: true,
|
|
95
97
|
props: {
|
|
@@ -101,7 +103,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
101
103
|
},
|
|
102
104
|
{
|
|
103
105
|
name: 'insert row after',
|
|
104
|
-
tooltip: 'media.tables.insertRowAfter',
|
|
106
|
+
tooltip: computed(() => t('media.tables.insertRowAfter')),
|
|
105
107
|
icon: mdi.mdiTableRowPlusAfter,
|
|
106
108
|
enabled: true,
|
|
107
109
|
props: {
|
|
@@ -113,7 +115,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
113
115
|
},
|
|
114
116
|
{
|
|
115
117
|
name: 'delete row',
|
|
116
|
-
tooltip: 'media.tables.deleteRow',
|
|
118
|
+
tooltip: computed(() => t('media.tables.deleteRow')),
|
|
117
119
|
icon: mdi.mdiTableRowRemove,
|
|
118
120
|
enabled: true,
|
|
119
121
|
props: {
|
|
@@ -127,7 +129,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
127
129
|
},
|
|
128
130
|
{
|
|
129
131
|
name: 'column',
|
|
130
|
-
tooltip: 'media.tables.col',
|
|
132
|
+
tooltip: computed(() => t('media.tables.col')),
|
|
131
133
|
icon: mdi.mdiTableColumn,
|
|
132
134
|
enabled: true,
|
|
133
135
|
props: {
|
|
@@ -145,7 +147,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
145
147
|
children: [
|
|
146
148
|
{
|
|
147
149
|
name: 'insert col before',
|
|
148
|
-
tooltip: 'media.tables.insertColBefore',
|
|
150
|
+
tooltip: computed(() => t('media.tables.insertColBefore')),
|
|
149
151
|
icon: mdi.mdiTableColumnPlusBefore,
|
|
150
152
|
enabled: true,
|
|
151
153
|
props: {
|
|
@@ -157,7 +159,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
157
159
|
},
|
|
158
160
|
{
|
|
159
161
|
name: 'insert column after',
|
|
160
|
-
tooltip: 'media.tables.insertColAfter',
|
|
162
|
+
tooltip: computed(() => t('media.tables.insertColAfter')),
|
|
161
163
|
icon: mdi.mdiTableColumnPlusAfter,
|
|
162
164
|
enabled: true,
|
|
163
165
|
props: {
|
|
@@ -169,7 +171,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
169
171
|
},
|
|
170
172
|
{
|
|
171
173
|
name: 'delete column',
|
|
172
|
-
tooltip: 'media.tables.deleteCol',
|
|
174
|
+
tooltip: computed(() => t('media.tables.deleteCol')),
|
|
173
175
|
icon: mdi.mdiTableColumnRemove,
|
|
174
176
|
enabled: true,
|
|
175
177
|
props: {
|
|
@@ -183,7 +185,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
183
185
|
},
|
|
184
186
|
{
|
|
185
187
|
name: 'merge cells',
|
|
186
|
-
tooltip: 'media.tables.mergeCells',
|
|
188
|
+
tooltip: computed(() => t('media.tables.mergeCells')),
|
|
187
189
|
icon: mdi.mdiTableMergeCells,
|
|
188
190
|
enabled: true,
|
|
189
191
|
props: {
|
|
@@ -195,7 +197,7 @@ export function getMediaItems(editor: Editor) {
|
|
|
195
197
|
},
|
|
196
198
|
{
|
|
197
199
|
name: 'split cell',
|
|
198
|
-
tooltip: 'media.tables.splitCell',
|
|
200
|
+
tooltip: computed(() => t('media.tables.splitCell')),
|
|
199
201
|
icon: mdi.mdiTableSplitCell,
|
|
200
202
|
enabled: true,
|
|
201
203
|
props: {
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as mdi from "@mdi/js";
|
|
2
2
|
import { Editor } from "@tiptap/vue-3";
|
|
3
3
|
import { computed } from "vue";
|
|
4
|
+
import { useI18n } from "vue-i18n";
|
|
5
|
+
|
|
6
|
+
export function useMiscItems(editor: Editor) {
|
|
7
|
+
const { t } = useI18n();
|
|
4
8
|
|
|
5
|
-
export function getMiscItems(editor: Editor) {
|
|
6
9
|
return {
|
|
7
10
|
line: {
|
|
8
11
|
name: 'line',
|
|
9
|
-
tooltip: 'format.line',
|
|
12
|
+
tooltip: computed(() => t('format.line')),
|
|
10
13
|
icon: mdi.mdiMinus,
|
|
11
14
|
enabled: true,
|
|
12
15
|
props: {},
|
|
@@ -16,7 +19,7 @@ export function getMiscItems(editor: Editor) {
|
|
|
16
19
|
},
|
|
17
20
|
break: {
|
|
18
21
|
name: 'break',
|
|
19
|
-
tooltip: 'format.break',
|
|
22
|
+
tooltip: computed(() => t('format.break')),
|
|
20
23
|
icon: mdi.mdiFormatPageBreak,
|
|
21
24
|
enabled: true,
|
|
22
25
|
props: {},
|
|
@@ -26,7 +29,7 @@ export function getMiscItems(editor: Editor) {
|
|
|
26
29
|
},
|
|
27
30
|
source: {
|
|
28
31
|
name: 'source',
|
|
29
|
-
tooltip: 'misc.source',
|
|
32
|
+
tooltip: computed(() => t('misc.source')),
|
|
30
33
|
icon: mdi.mdiCodeTags,
|
|
31
34
|
enabled: true,
|
|
32
35
|
props: {},
|
|
@@ -36,7 +39,7 @@ export function getMiscItems(editor: Editor) {
|
|
|
36
39
|
},
|
|
37
40
|
preview: {
|
|
38
41
|
name: 'preview',
|
|
39
|
-
tooltip: 'misc.preview',
|
|
42
|
+
tooltip: computed(() => t('misc.preview')),
|
|
40
43
|
icon: mdi.mdiFileEyeOutline,
|
|
41
44
|
enabled: true,
|
|
42
45
|
attrs: {
|
|
@@ -45,7 +48,7 @@ export function getMiscItems(editor: Editor) {
|
|
|
45
48
|
},
|
|
46
49
|
formatClear: {
|
|
47
50
|
name: 'format clear',
|
|
48
|
-
tooltip: 'format.formatClear',
|
|
51
|
+
tooltip: computed(() => t('format.formatClear')),
|
|
49
52
|
icon: mdi.mdiFormatClear,
|
|
50
53
|
enabled: true,
|
|
51
54
|
props: {
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import * as mdi from "@mdi/js";
|
|
2
|
+
import { Level } from "@tiptap/extension-heading";
|
|
3
|
+
import FontFamily from "@tiptapify/extensions/components/FontFamily.vue";
|
|
4
|
+
import FontSize from "@tiptapify/extensions/components/FontSize.vue";
|
|
5
|
+
import LineHeight from "@tiptapify/extensions/components/LineHeight.vue";
|
|
6
|
+
import { Editor } from "@tiptap/vue-3";
|
|
7
|
+
import StyleColor from "@tiptapify/extensions/components/StyleColor.vue";
|
|
8
|
+
import { computed, markRaw } from "vue";
|
|
9
|
+
import { useI18n } from "vue-i18n";
|
|
10
|
+
import {
|
|
11
|
+
fonts,
|
|
12
|
+
fontSizes,
|
|
13
|
+
lineHeights,
|
|
14
|
+
headingLevels,
|
|
15
|
+
setHeadingLevels,
|
|
16
|
+
defaultFontSize,
|
|
17
|
+
defaultLineHeight
|
|
18
|
+
} from "@tiptapify/constants/style";
|
|
19
|
+
|
|
20
|
+
interface MDIIcons {
|
|
21
|
+
[key: string]: string
|
|
22
|
+
}
|
|
23
|
+
const mdiIcons = mdi as MDIIcons
|
|
24
|
+
|
|
25
|
+
export function useStyleItems(editor: Editor, theme: any, fontMeasure: string, customHeadingLevels: Array<number> = []) {
|
|
26
|
+
const { t } = useI18n();
|
|
27
|
+
|
|
28
|
+
setHeadingLevels(customHeadingLevels)
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
heading: {
|
|
32
|
+
name: 'heading',
|
|
33
|
+
tooltip: computed(() => t('style.heading')),
|
|
34
|
+
icon: mdi.mdiFormatHeaderPound,
|
|
35
|
+
modelValue: null,
|
|
36
|
+
enabled: true,
|
|
37
|
+
props: {
|
|
38
|
+
color: computed(() => editor.isActive('heading') || editor.isActive('paragraph') ? 'primary' : ''),
|
|
39
|
+
},
|
|
40
|
+
children: [
|
|
41
|
+
{
|
|
42
|
+
name: 'paragraph',
|
|
43
|
+
tooltip: computed(() => t('style.paragraph')),
|
|
44
|
+
icon: mdiIcons['mdiFormatParagraph'],
|
|
45
|
+
noI18n: true,
|
|
46
|
+
enabled: true,
|
|
47
|
+
props: {
|
|
48
|
+
color: computed(() => editor.isActive('paragraph') ? 'primary' : ''),
|
|
49
|
+
},
|
|
50
|
+
attrs: {
|
|
51
|
+
click: () => editor.chain().focus().setParagraph().run()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
].concat(
|
|
55
|
+
headingLevels.value.map(level => {
|
|
56
|
+
const headingLevel: Level = level as Level
|
|
57
|
+
return {
|
|
58
|
+
name: `H${level}`,
|
|
59
|
+
tooltip: computed(() => t(`style.headings.h${level}`)),
|
|
60
|
+
icon: mdiIcons[`mdiFormatHeader${level}`],
|
|
61
|
+
noI18n: true,
|
|
62
|
+
enabled: true,
|
|
63
|
+
props: {
|
|
64
|
+
color: computed(() => editor.isActive('heading', { level: level }) ? 'primary' : ''),
|
|
65
|
+
},
|
|
66
|
+
attrs: {
|
|
67
|
+
click: () => editor.chain().focus().toggleHeading({ level: headingLevel }).run()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
)
|
|
72
|
+
},
|
|
73
|
+
fontFamily: {
|
|
74
|
+
name: 'font-family',
|
|
75
|
+
tooltip: computed(() => t('style.fontFamily')),
|
|
76
|
+
icon: mdi.mdiFormatFont,
|
|
77
|
+
modelValue: false,
|
|
78
|
+
enabled: true,
|
|
79
|
+
props: {
|
|
80
|
+
disabled: computed(() => !editor.can().chain().focus().unsetFontFamily().run()),
|
|
81
|
+
color: computed(() => {
|
|
82
|
+
let color = ''
|
|
83
|
+
for (const font in fonts) {
|
|
84
|
+
if (editor.isActive('textStyle', { fontFamily: fonts[font].fontFamily })) {
|
|
85
|
+
color = 'primary'
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return color
|
|
91
|
+
}),
|
|
92
|
+
},
|
|
93
|
+
component: markRaw(FontFamily),
|
|
94
|
+
componentProps: {
|
|
95
|
+
fonts: fonts,
|
|
96
|
+
fontFamily: computed(() => {
|
|
97
|
+
let fontFamily = ''
|
|
98
|
+
for (const font in fonts) {
|
|
99
|
+
if (editor.isActive('textStyle', { fontFamily: fonts[font].fontFamily })) {
|
|
100
|
+
fontFamily = fonts[font].fontFamily
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return fontFamily
|
|
106
|
+
}),
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
fontSize: {
|
|
110
|
+
name: 'font-size',
|
|
111
|
+
tooltip: computed(() => t('style.fontSize')),
|
|
112
|
+
icon: mdi.mdiFormatSize,
|
|
113
|
+
modelValue: false,
|
|
114
|
+
enabled: true,
|
|
115
|
+
props: {
|
|
116
|
+
disabled: computed(() => !editor.can().chain().focus().unsetFontSize().run()),
|
|
117
|
+
color: computed(() => {
|
|
118
|
+
let color = ''
|
|
119
|
+
for (const size of fontSizes) {
|
|
120
|
+
if (editor.isActive('textStyle', { fontSize: `${size}${fontMeasure}` })) {
|
|
121
|
+
color = 'primary'
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return color
|
|
127
|
+
}),
|
|
128
|
+
},
|
|
129
|
+
component: markRaw(FontSize),
|
|
130
|
+
componentProps: {
|
|
131
|
+
sizes: fontSizes,
|
|
132
|
+
measure: fontMeasure,
|
|
133
|
+
fontSize: computed(() => {
|
|
134
|
+
let fontSize = null
|
|
135
|
+
for (const size of fontSizes) {
|
|
136
|
+
if (editor.isActive('textStyle', { fontSize: `${size}${fontMeasure}` })) {
|
|
137
|
+
fontSize = size
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return fontSize
|
|
143
|
+
}),
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
lineHeight: {
|
|
147
|
+
name: 'line-height',
|
|
148
|
+
tooltip: computed(() => t('style.lineHeight')),
|
|
149
|
+
icon: mdi.mdiFormatLineHeight,
|
|
150
|
+
modelValue: null,
|
|
151
|
+
enabled: true,
|
|
152
|
+
props: {
|
|
153
|
+
disabled: computed(() => !editor.can().chain().focus().unsetLineHeight().run()),
|
|
154
|
+
color: computed(() => {
|
|
155
|
+
let color = ''
|
|
156
|
+
for (const height of lineHeights) {
|
|
157
|
+
if (editor.isActive('textStyle', { lineHeight: height.toString() })) {
|
|
158
|
+
color = 'primary'
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return color
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
component: markRaw(LineHeight),
|
|
167
|
+
componentProps: {
|
|
168
|
+
lineHeights,
|
|
169
|
+
lineHeight: computed(() => {
|
|
170
|
+
let lineHeight = null
|
|
171
|
+
for (const height of lineHeights) {
|
|
172
|
+
if (editor.isActive('textStyle', { lineHeight: height.toString() })) {
|
|
173
|
+
lineHeight = height
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return lineHeight
|
|
179
|
+
}),
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
highlight: {
|
|
183
|
+
name: 'highlight',
|
|
184
|
+
tooltip: computed(() => t('style.color.highlight')),
|
|
185
|
+
icon: mdi.mdiFormatColorFill,
|
|
186
|
+
icon2: mdi.mdiColorHelper,
|
|
187
|
+
enabled: true,
|
|
188
|
+
props: {
|
|
189
|
+
disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
|
|
190
|
+
},
|
|
191
|
+
icon2Props: {
|
|
192
|
+
disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
|
|
193
|
+
color: computed(() => {
|
|
194
|
+
const defaultColor = theme.global.current.value.dark ? '#fff' : '#000'
|
|
195
|
+
return editor.getAttributes('highlight').color || defaultColor
|
|
196
|
+
}),
|
|
197
|
+
style: 'filter: drop-shadow(rgba(0, 0, 0, .75) 1px 1px 2px);'
|
|
198
|
+
},
|
|
199
|
+
component: markRaw(StyleColor),
|
|
200
|
+
componentProps: {
|
|
201
|
+
fontColor: false,
|
|
202
|
+
backgroundColor: true,
|
|
203
|
+
color: computed(() => editor.getAttributes('highlight').color || ''),
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
color: {
|
|
207
|
+
name: 'color',
|
|
208
|
+
tooltip: computed(() => t('style.color.text')),
|
|
209
|
+
icon: mdi.mdiFormatColorText,
|
|
210
|
+
icon2: mdi.mdiColorHelper,
|
|
211
|
+
enabled: true,
|
|
212
|
+
props: {
|
|
213
|
+
disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
|
|
214
|
+
},
|
|
215
|
+
icon2Props: {
|
|
216
|
+
disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
|
|
217
|
+
color: computed(() => {
|
|
218
|
+
const defaultColor = theme.global.current.value.dark ? '#fff' : '#000'
|
|
219
|
+
return editor.getAttributes('textStyle').color || defaultColor
|
|
220
|
+
}),
|
|
221
|
+
style: 'filter: drop-shadow(rgba(0, 0, 0, .75) 1px 1px 2px);'
|
|
222
|
+
},
|
|
223
|
+
component: markRaw(StyleColor),
|
|
224
|
+
componentProps: {
|
|
225
|
+
fontColor: true,
|
|
226
|
+
backgroundColor: false,
|
|
227
|
+
color: computed(() => editor.getAttributes('textStyle').color || ''),
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
|
|
3
|
+
export const defaultFontSize = 12
|
|
4
|
+
export const fontSizes = [6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 32, 48, 64, 96]
|
|
5
|
+
|
|
6
|
+
export const defaultLineHeight = 1
|
|
7
|
+
export const lineHeights = [1, 1.5, 2, 3, 4]
|
|
8
|
+
|
|
9
|
+
export const headingLevels = ref([1, 2, 3, 4, 5, 6])
|
|
10
|
+
export function setHeadingLevels(customHeadingLevels: number[]) {
|
|
11
|
+
if (customHeadingLevels.length) {
|
|
12
|
+
customHeadingLevels.forEach(level => {
|
|
13
|
+
if (level < 1 || level > 6) {
|
|
14
|
+
throw new Error('customHeadingLevels must be between 1 and 6')
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
headingLevels.value = customHeadingLevels
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
1
22
|
export const fonts = [
|
|
2
23
|
{
|
|
3
24
|
name: 'Arial',
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
|
|
3
|
+
import { Editor } from "@tiptap/vue-3";
|
|
4
|
+
|
|
5
|
+
import { computed, inject, Ref, ref } from 'vue'
|
|
6
|
+
import { useI18n } from "vue-i18n";
|
|
7
|
+
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
fonts: { type: Array<{ name: string, fontFamily: string }>, default: [] },
|
|
10
|
+
fontFamily: { type: String, default: '' },
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const { t } = useI18n();
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits(['close'])
|
|
16
|
+
|
|
17
|
+
const editor = inject('tiptapifyEditor') as Ref<Editor>
|
|
18
|
+
|
|
19
|
+
const initialFontFamily = ref(computed(() => props.fontFamily).value)
|
|
20
|
+
|
|
21
|
+
const fontSelected = ref<boolean>(false)
|
|
22
|
+
|
|
23
|
+
function hoverFontFamily(font: string) {
|
|
24
|
+
fontSelected.value = false
|
|
25
|
+
|
|
26
|
+
editor.value.chain().focus().setFontFamily(font).run()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function resetFontFamily() {
|
|
30
|
+
if (fontSelected.value) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
initialFontFamily.value
|
|
35
|
+
? editor.value.chain().focus().setFontFamily(initialFontFamily.value).run()
|
|
36
|
+
: editor.value.chain().focus().unsetFontFamily().run()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function clearFontFamily() {
|
|
40
|
+
editor.value.chain().focus().unsetFontFamily().run()
|
|
41
|
+
emit('close')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function setFontFamily() {
|
|
45
|
+
fontSelected.value = true
|
|
46
|
+
|
|
47
|
+
emit('close')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isFontFamilyActive(fontFamily: string): boolean {
|
|
51
|
+
return editor.value.isActive('textStyle', { fontFamily }) || fontFamily === initialFontFamily.value
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<VList class="tiptapify-font-family-list">
|
|
57
|
+
<VListItem :disabled="fontFamily === ''" density="compact" @click="clearFontFamily">
|
|
58
|
+
<VListItemTitle class="font-italic text-grey-darken-1">
|
|
59
|
+
{{ t('defaultValue') }}
|
|
60
|
+
</VListItemTitle>
|
|
61
|
+
</VListItem>
|
|
62
|
+
<VListItem
|
|
63
|
+
v-for="font in fonts"
|
|
64
|
+
:active="isFontFamilyActive(font.fontFamily)"
|
|
65
|
+
:color="font.fontFamily === initialFontFamily ? 'primary' : ''"
|
|
66
|
+
density="compact"
|
|
67
|
+
@click="setFontFamily"
|
|
68
|
+
@mouseover="hoverFontFamily(font.fontFamily)"
|
|
69
|
+
@mouseleave="resetFontFamily"
|
|
70
|
+
>
|
|
71
|
+
<VListItemTitle>
|
|
72
|
+
{{ font.name }}
|
|
73
|
+
</VListItemTitle>
|
|
74
|
+
</VListItem>
|
|
75
|
+
</VList>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<style lang="scss" scoped>
|
|
79
|
+
.tiptapify-font-family-list {
|
|
80
|
+
max-height: 390px;
|
|
81
|
+
}
|
|
82
|
+
</style>
|