tiptapify 0.0.8 → 0.0.10

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.
Files changed (44) hide show
  1. package/README.md +25 -2
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/tiptapify.mjs +26215 -22992
  4. package/dist/tiptapify.umd.js +39 -39
  5. package/index.d.ts +49 -0
  6. package/package.json +10 -8
  7. package/src/components/Footer.vue +48 -6
  8. package/src/components/Tiptapify.vue +37 -29
  9. package/src/components/Toolbar/Group.vue +13 -14
  10. package/src/components/Toolbar/GroupBtn.vue +30 -0
  11. package/src/components/Toolbar/GroupDropdown.vue +4 -8
  12. package/src/components/Toolbar/Index.vue +26 -77
  13. package/src/components/Toolbar/Items.vue +77 -0
  14. package/src/components/Toolbar/defaultExtensionComponents.ts +32 -0
  15. package/src/components/Toolbar/items/format.ts +7 -20
  16. package/src/components/Toolbar/items/formatExtra.ts +1 -1
  17. package/src/components/Toolbar/items/media.ts +1 -1
  18. package/src/components/Toolbar/items/misc.ts +1 -1
  19. package/src/components/Toolbar/items/style.ts +60 -2
  20. package/src/components/Toolbar/items.ts +6 -4
  21. package/src/components/UI/Dialog.vue +141 -0
  22. package/src/components/editorExtensions.ts +3 -7
  23. package/src/extensions/components/ImageDialog.vue +17 -29
  24. package/src/extensions/components/LinkDialog.vue +58 -43
  25. package/src/extensions/components/PreviewDialog.vue +8 -16
  26. package/src/extensions/components/ShowSourceDialog.vue +14 -16
  27. package/src/extensions/components/StyleColor.vue +230 -0
  28. package/src/extensions/components/TableBuilder.vue +4 -8
  29. package/src/i18n/locales/ch.json +118 -0
  30. package/src/i18n/locales/cz.json +118 -0
  31. package/src/i18n/locales/de.json +90 -72
  32. package/src/i18n/locales/en.json +89 -71
  33. package/src/i18n/locales/es.json +90 -72
  34. package/src/i18n/locales/fr.json +91 -72
  35. package/src/i18n/locales/it.json +90 -72
  36. package/src/i18n/locales/la.json +118 -0
  37. package/src/i18n/locales/lt.json +118 -0
  38. package/src/i18n/locales/nl.json +118 -0
  39. package/src/i18n/locales/pl.json +90 -72
  40. package/src/i18n/locales/pt.json +118 -0
  41. package/src/i18n/locales/ru.json +85 -67
  42. package/src/i18n/locales/se.json +118 -0
  43. package/src/i18n/locales/ua.json +86 -68
  44. package/src/types/overridable-extensions.ts +6 -0
@@ -0,0 +1,77 @@
1
+ <script setup lang="ts">
2
+ import Group from "@tiptapify/components/Toolbar/Group.vue";
3
+ import Toggle from "@tiptapify/components/Toolbar/Toggle.vue";
4
+ import { computed, defineProps, PropType, Ref, ref } from 'vue'
5
+ import { useI18n } from "vue-i18n";
6
+
7
+ import { ToolbarItemSections } from "@tiptapify/components/Toolbar/items";
8
+
9
+ const props = defineProps({
10
+ variantBtn: { type: String, default () { return 'elevated' }},
11
+ items: { type: Object as PropType<ToolbarItemSections>, default() { return {} }},
12
+ })
13
+
14
+ const { t } = useI18n();
15
+
16
+ const toolbarItemsRef: Ref<ToolbarItemSections> = ref(computed(() => props.items).value)
17
+
18
+ </script>
19
+
20
+ <template>
21
+ <VToolbarItems class="py-2">
22
+ <template v-for="(toolbarSection, sectionKey) in toolbarItemsRef" :key="sectionKey">
23
+ <Group v-if="toolbarSection.group" :variant="variantBtn" :toolbar-section="toolbarSection" />
24
+
25
+ <Toggle v-else-if="toolbarSection.toggle" :variant="variantBtn" :toolbar-section="toolbarSection" />
26
+
27
+ <VBtn
28
+ v-else
29
+ v-for="(toolbarItem, itemKey) in toolbarSection.items"
30
+ :key="itemKey"
31
+ :variant="variantBtn"
32
+ v-bind="toolbarItem.props"
33
+ v-on="toolbarItem.attrs"
34
+ class="menu-button"
35
+ size="32"
36
+ elevation="4"
37
+ rounded="sm"
38
+ >
39
+ <VTooltip :text="t(toolbarItem.tooltip)" location="top" activator="parent" />
40
+
41
+ <VIcon v-if="toolbarItem.icon" :icon="toolbarItem.icon" size="16" />
42
+ <span v-else class="menu-item-title">
43
+ {{ t(toolbarItem.name) }}
44
+ </span>
45
+ </VBtn>
46
+
47
+ <div class="menu-divider"></div>
48
+ </template>
49
+ </VToolbarItems>
50
+ </template>
51
+
52
+ <style lang="scss" scoped>
53
+ :deep(.v-btn-group) {
54
+ height: 32px !important;
55
+ }
56
+
57
+ .menu-item-title {
58
+ font-size: 14px;
59
+ }
60
+
61
+ .menu-button {
62
+ margin: 0 1px;
63
+ }
64
+
65
+ .menu-divider {
66
+ margin: 0 4px;
67
+ }
68
+
69
+ .menu-divider:nth-last-child(1) {
70
+ display: none;
71
+ }
72
+
73
+ .v-toolbar-items {
74
+ flex-wrap: wrap;
75
+ row-gap: 5px;
76
+ }
77
+ </style>
@@ -0,0 +1,32 @@
1
+ import ImageDialog from "@tiptapify/extensions/components/ImageDialog.vue";
2
+ import LinkDialog from "@tiptapify/extensions/components/LinkDialog.vue";
3
+ import PreviewDialog from "@tiptapify/extensions/components/PreviewDialog.vue";
4
+ import ShowSourceDialog from "@tiptapify/extensions/components/ShowSourceDialog.vue";
5
+ import { extensionsComponents } from "@tiptapify/types/overridable-extensions";
6
+ import { computed } from "vue";
7
+
8
+ export function getDefaultComponents(variantField: string): extensionsComponents {
9
+ return {
10
+ image: {
11
+ component: ImageDialog,
12
+ props: {
13
+ variantField: computed(() => variantField).value,
14
+ }
15
+ },
16
+ link: {
17
+ component: LinkDialog,
18
+ props: {
19
+ variantField: computed(() => variantField).value,
20
+ }
21
+ },
22
+ preview: {
23
+ component: PreviewDialog,
24
+ },
25
+ showSource: {
26
+ component: ShowSourceDialog,
27
+ props: {
28
+ variantField: computed(() => variantField).value,
29
+ }
30
+ }
31
+ }
32
+ }
@@ -30,19 +30,6 @@ export function getFormatItems(editor: Editor) {
30
30
  click: () => editor.chain().focus().toggleItalic().run()
31
31
  }
32
32
  },
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
33
  underline: {
47
34
  name: 'underline',
48
35
  tooltip: 'format.underline',
@@ -56,17 +43,17 @@ export function getFormatItems(editor: Editor) {
56
43
  click: () => editor.chain().focus().toggleUnderline().run()
57
44
  }
58
45
  },
59
- highlight: {
60
- name: 'highlight',
61
- tooltip: 'format.highlight',
62
- icon: mdi.mdiMarker,
46
+ strike: {
47
+ name: 'strike',
48
+ tooltip: 'format.strike',
49
+ icon: mdi.mdiFormatStrikethroughVariant,
63
50
  enabled: true,
64
51
  props: {
65
- disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
66
- color: computed(() => editor.isActive('highlight') ? 'primary' : ''),
52
+ disabled: computed(() => !editor.can().chain().focus().toggleStrike().run()),
53
+ color: computed(() => editor.isActive('strike') ? 'primary' : ''),
67
54
  },
68
55
  attrs: {
69
- click: () => editor.chain().focus().toggleHighlight().run()
56
+ click: () => editor.chain().focus().toggleStrike().run()
70
57
  }
71
58
  }
72
59
  }
@@ -62,7 +62,7 @@ export function getFormatExtraItems(editor: Editor) {
62
62
  icon: mdi.mdiCommentQuote,
63
63
  enabled: true,
64
64
  props: {
65
- disabled: computed(() => !editor.can().chain().focus().toggleBlockquote().run()),
65
+ disabled: computed(() => !editor.can().chain().focus().toggleBlockquote().run() || editor.isActive('codeBlock') || editor.isActive('code')),
66
66
  color: computed(() => editor.isActive('blockquote') ? 'primary' : ''),
67
67
  },
68
68
  attrs: {
@@ -1,7 +1,7 @@
1
1
  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
- import { computed, markRaw, Ref } from "vue";
4
+ import { computed, markRaw } from "vue";
5
5
 
6
6
  export function getMediaItems(editor: Editor) {
7
7
  return {
@@ -1,6 +1,6 @@
1
1
  import * as mdi from "@mdi/js";
2
2
  import { Editor } from "@tiptap/vue-3";
3
- import { computed, Ref } from "vue";
3
+ import { computed } from "vue";
4
4
 
5
5
  export function getMiscItems(editor: Editor) {
6
6
  return {
@@ -1,14 +1,15 @@
1
1
  import * as mdi from "@mdi/js";
2
2
  import { Editor } from "@tiptap/vue-3";
3
3
  import { fonts } from "@tiptapify/components/Toolbar/fonts";
4
- import { computed, ref } from "vue";
4
+ import StyleColor from "@tiptapify/extensions/components/StyleColor.vue";
5
+ import { computed, markRaw, ref } from "vue";
5
6
 
6
7
  interface MDIIcons {
7
8
  [key: string]: string
8
9
  }
9
10
  const mdiIcons = mdi as MDIIcons
10
11
 
11
- export function getStyleItems(editor: Editor, fontMeasure: string, customHeadingLevels: Array<number> = []) {
12
+ export function getStyleItems(editor: Editor, theme: any, fontMeasure: string, customHeadingLevels: Array<number> = []) {
12
13
  const headingLevels = ref([1, 2, 3, 4, 5, 6])
13
14
  if (customHeadingLevels.length) {
14
15
  customHeadingLevels.forEach(level => {
@@ -72,6 +73,9 @@ export function getStyleItems(editor: Editor, fontMeasure: string, customHeading
72
73
  icon: mdi.mdiFormatFont,
73
74
  modelValue: false,
74
75
  enabled: true,
76
+ props: {
77
+ disabled: computed(() => !editor.can().chain().focus().unsetFontFamily().run()),
78
+ },
75
79
  attrs: {
76
80
  click: () => editor.chain().focus().unsetFontFamily().run()
77
81
  },
@@ -98,6 +102,9 @@ export function getStyleItems(editor: Editor, fontMeasure: string, customHeading
98
102
  icon: mdi.mdiFormatSize,
99
103
  modelValue: false,
100
104
  enabled: true,
105
+ props: {
106
+ disabled: computed(() => !editor.can().chain().focus().unsetFontSize().run()),
107
+ },
101
108
  attrs: {
102
109
  click: () => editor.chain().focus().unsetFontSize().run()
103
110
  },
@@ -123,6 +130,9 @@ export function getStyleItems(editor: Editor, fontMeasure: string, customHeading
123
130
  icon: mdi.mdiFormatLineHeight,
124
131
  modelValue: null,
125
132
  enabled: true,
133
+ props: {
134
+ disabled: computed(() => !editor.can().chain().focus().unsetLineHeight().run()),
135
+ },
126
136
  attrs: {
127
137
  click: () => editor.chain().focus().unsetLineHeight().run()
128
138
  },
@@ -141,6 +151,54 @@ export function getStyleItems(editor: Editor, fontMeasure: string, customHeading
141
151
  }
142
152
  }
143
153
  })
154
+ },
155
+ highlight: {
156
+ name: 'highlight',
157
+ tooltip: 'style.color.highlight',
158
+ icon: mdi.mdiFormatColorFill,
159
+ icon2: mdi.mdiColorHelper,
160
+ enabled: true,
161
+ props: {
162
+ disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
163
+ },
164
+ icon2Props: {
165
+ disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
166
+ color: computed(() => {
167
+ const defaultColor = theme.global.current.value.dark ? '#fff' : '#000'
168
+ return editor.getAttributes('highlight').color || defaultColor
169
+ }),
170
+ style: 'filter: drop-shadow(rgba(0, 0, 0, .75) 1px 1px 2px);'
171
+ },
172
+ component: markRaw(StyleColor),
173
+ componentProps: {
174
+ fontColor: false,
175
+ backgroundColor: true,
176
+ color: computed(() => editor.getAttributes('highlight').color || ''),
177
+ }
178
+ },
179
+ color: {
180
+ name: 'color',
181
+ tooltip: 'style.color.text',
182
+ icon: mdi.mdiFormatColorText,
183
+ icon2: mdi.mdiColorHelper,
184
+ enabled: true,
185
+ props: {
186
+ disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
187
+ },
188
+ icon2Props: {
189
+ disabled: computed(() => !editor.can().chain().focus().toggleHighlight().run()),
190
+ color: computed(() => {
191
+ const defaultColor = theme.global.current.value.dark ? '#fff' : '#000'
192
+ return editor.getAttributes('textStyle').color || defaultColor
193
+ }),
194
+ style: 'filter: drop-shadow(rgba(0, 0, 0, .75) 1px 1px 2px);'
195
+ },
196
+ component: markRaw(StyleColor),
197
+ componentProps: {
198
+ fontColor: true,
199
+ backgroundColor: false,
200
+ color: computed(() => editor.getAttributes('textStyle').color || ''),
201
+ }
144
202
  }
145
203
  }
146
204
  }
@@ -6,7 +6,7 @@ import { getListItems } from "@tiptapify/components/Toolbar/items/list";
6
6
  import { getMediaItems } from "@tiptapify/components/Toolbar/items/media";
7
7
  import { getMiscItems } from "@tiptapify/components/Toolbar/items/misc";
8
8
  import { getStyleItems } from "@tiptapify/components/Toolbar/items/style";
9
- import { ComputedRef, Ref, ref } from "vue";
9
+ import { ComputedRef, ref } from "vue";
10
10
 
11
11
  interface ToolbarItemAttrs {
12
12
  [key: string]: Function | any
@@ -20,12 +20,15 @@ export interface ToolbarItem {
20
20
  name: string|number,
21
21
  tooltip: string,
22
22
  icon: string|ComputedRef<string>,
23
+ icon2?: string|ComputedRef<string>,
23
24
  noI18n?: boolean,
24
25
  enabled: boolean,
25
26
  component?: any,
26
27
  modelValue?: any,
27
28
  group?: boolean,
28
29
  toggle?: boolean,
30
+ icon2Props?: ToolbarItemProps,
31
+ componentProps?: ToolbarItemProps,
29
32
  props?: ToolbarItemProps,
30
33
  attrs?: ToolbarItemAttrs,
31
34
  children?: ToolbarItems|ToolbarItem[],
@@ -47,11 +50,12 @@ export interface ToolbarItemSections {
47
50
 
48
51
  export function toolbarItems(
49
52
  editor: any,
53
+ theme: any,
50
54
  fontMeasure: string,
51
55
  items: { list: Array<string>, exclude: boolean },
52
56
  customHeadingLevels: Array<number>
53
57
  ): ToolbarItemSections {
54
- const styleItems = ref(getStyleItems(editor.value, fontMeasure, customHeadingLevels))
58
+ const styleItems = ref(getStyleItems(editor.value, theme, fontMeasure, customHeadingLevels))
55
59
  const formatItems = ref(getFormatItems(editor.value))
56
60
  const formatExtraItems = ref(getFormatExtraItems(editor.value))
57
61
  const alignmentItems = ref(getAlignmentItems(editor.value))
@@ -64,8 +68,6 @@ export function toolbarItems(
64
68
  /**
65
69
  * todo
66
70
  *
67
- * font color, backgroundcolor
68
- * tables
69
71
  * media (image, video)
70
72
  */
71
73
  style: { group: true, items: styleItems.value },
@@ -0,0 +1,141 @@
1
+ <script lang="ts" setup>
2
+
3
+ import * as mdi from "@mdi/js";
4
+ import { nextTick, ref, watch } from "vue";
5
+ import { useI18n } from "vue-i18n";
6
+
7
+ const props = defineProps({
8
+ module: String,
9
+ fullscreen: { type: Boolean, default () { return false } },
10
+ maxWidth: { type: Number, default () { return 800 } },
11
+ })
12
+
13
+ const { t } = useI18n();
14
+
15
+ defineExpose({ open, close })
16
+ const emits = defineEmits(['closeDialog'])
17
+
18
+ const dialog = ref<boolean>(false)
19
+ const movableHandler = ref(null)
20
+
21
+ function open() {
22
+ dialog.value = true
23
+ }
24
+
25
+ function close() {
26
+ dialog.value = false
27
+ }
28
+
29
+ function emitClose() {
30
+ emits('closeDialog')
31
+
32
+ close()
33
+ }
34
+
35
+ function dragElement(trigger: HTMLElement, container: HTMLElement) {
36
+ const coordinates = {
37
+ moveX: 0,
38
+ moveY: 0,
39
+ cursorX: 0,
40
+ cursorY: 0,
41
+ }
42
+
43
+ trigger.onmousedown = dragMouseDown
44
+
45
+ function dragMouseDown(e: MouseEvent) {
46
+ e.preventDefault()
47
+
48
+ coordinates.cursorX = e.clientX
49
+ coordinates.cursorY = e.clientY
50
+
51
+ document.onmouseup = closeDragElement
52
+ document.onmousemove = elementDrag
53
+ }
54
+
55
+ function elementDrag(e: MouseEvent) {
56
+ e.preventDefault();
57
+
58
+ coordinates.moveX = coordinates.cursorX - e.clientX
59
+ coordinates.moveY = coordinates.cursorY - e.clientY
60
+ coordinates.cursorX = e.clientX
61
+ coordinates.cursorY = e.clientY
62
+
63
+ const parentOffsetLeft = container.parentNode.offsetLeft
64
+ const parentOffsetTop = container.parentNode.offsetTop
65
+
66
+ let left = container.offsetLeft - coordinates.moveX
67
+ if (left < (parentOffsetLeft * -1)) {
68
+ left = (parentOffsetLeft * -1)
69
+ }
70
+ if (left >= parentOffsetLeft) {
71
+ left = parentOffsetLeft
72
+ }
73
+
74
+ let top = container.offsetTop - coordinates.moveY
75
+ if (top < (parentOffsetTop * -1)) {
76
+ top = (parentOffsetTop * -1)
77
+ }
78
+ if (top >= parentOffsetTop) {
79
+ top = parentOffsetTop
80
+ }
81
+
82
+ container.style.left = `${left}px`
83
+ container.style.top = `${top}px`
84
+ }
85
+
86
+ function closeDragElement() {
87
+ document.onmouseup = null
88
+ document.onmousemove = null
89
+ }
90
+ }
91
+
92
+ watch(() => dialog.value, async () => {
93
+ await nextTick()
94
+
95
+ if (!movableHandler.value) {
96
+ return
97
+ }
98
+
99
+ if (dialog.value && !props.fullscreen) {
100
+ dragElement(movableHandler.value.$el as HTMLElement, movableHandler.value.$el.parentNode as HTMLElement)
101
+ }
102
+ })
103
+ </script>
104
+
105
+ <template>
106
+ <VDialog v-model="dialog" :max-width="maxWidth" :fullscreen="fullscreen" absolute @click:outside="emitClose">
107
+ <VCard>
108
+ <VCardTitle ref="movableHandler" :class="`d-flex ${!fullscreen ? 'tiptapify-movable-handler' : ''}`" style="user-select: none;">
109
+ <VLabel>
110
+ {{ t(`dialog.${module}.title`) }}
111
+ </VLabel>
112
+
113
+ <VSpacer />
114
+
115
+ <VBtn density="compact" class="tiptapify-dialog-close" variant="elevated" elevation="4" icon @click="emitClose">
116
+ <VIcon size="x-small" :icon="mdi.mdiClose" />
117
+ </VBtn>
118
+ </VCardTitle>
119
+
120
+ <VDivider />
121
+
122
+ <slot name="content" />
123
+
124
+ <slot name="actions" />
125
+ </VCard>
126
+ </VDialog>
127
+ </template>
128
+
129
+ <style lang="scss" scoped>
130
+ :deep(.v-overlay__content) {
131
+ position: fixed;
132
+ }
133
+
134
+ .tiptapify-movable-handler, :deep(.tiptapify-movable-handler > *) {
135
+ cursor: move;
136
+ }
137
+
138
+ .tiptapify-dialog-close:hover {
139
+ cursor: pointer;
140
+ }
141
+ </style>
@@ -69,7 +69,7 @@ export function editorExtensions (placeholder: string, slashCommands: boolean) {
69
69
  Dropcursor,
70
70
  Typography,
71
71
  Underline,
72
- Highlight,
72
+ Highlight.configure({ multicolor: true }),
73
73
  TiptapifyLink.configure({
74
74
  openOnClick: false,
75
75
  defaultProtocol: 'https'
@@ -89,12 +89,8 @@ export function editorExtensions (placeholder: string, slashCommands: boolean) {
89
89
  },
90
90
  })
91
91
  .configure({ lowlight }),
92
- Selection.configure({
93
- className: 'selection',
94
- }),
95
- TextAlign.configure({
96
- types: ['heading', 'paragraph'],
97
- }),
92
+ Selection.configure({ className: 'selection' }),
93
+ TextAlign.configure({ types: ['heading', 'paragraph'] }),
98
94
  Placeholder.configure({ placeholder }),
99
95
  CharacterCount,
100
96
  ViewSource,
@@ -1,20 +1,16 @@
1
1
  <script setup lang="ts">
2
2
 
3
- import * as mdi from '@mdi/js'
4
3
  import { Editor } from "@tiptap/vue-3";
4
+ import Dialog from "@tiptapify/components/UI/Dialog.vue";
5
5
 
6
6
  import { useI18n } from 'vue-i18n'
7
7
  import { computed, inject, onMounted, onUnmounted, Ref, ref } from 'vue'
8
8
 
9
- import helpers from '@tiptapify/utils/helpers'
10
-
11
9
  defineProps({
12
10
  variantBtn: { type: String, default() { return 'elevated' }},
13
11
  variantField: { type: String, default() { return 'solo' }}
14
12
  })
15
13
 
16
- const { ucFirst } = helpers
17
-
18
14
  const editor = inject('tiptapifyEditor') as Ref<Editor>
19
15
  const { t } = useI18n()
20
16
 
@@ -27,7 +23,7 @@ const generateImageAttrs = () => ({
27
23
 
28
24
  const attrs = ref(generateImageAttrs())
29
25
 
30
- const dialog = ref<boolean>(false)
26
+ const dialog = ref(null)
31
27
 
32
28
  const isDisabled = computed(() => {
33
29
  const { src } = attrs.value
@@ -64,7 +60,7 @@ function clear() {
64
60
  }
65
61
 
66
62
  function close() {
67
- dialog.value = false
63
+ dialog.value.close()
68
64
 
69
65
  attrs.value = generateImageAttrs()
70
66
  }
@@ -75,7 +71,7 @@ const showTiptapifyImage = (event: CustomEvent) => {
75
71
  attrs.value.width = event.detail.image?.width
76
72
  attrs.value.height = event.detail.image?.height
77
73
 
78
- dialog.value = true;
74
+ dialog.value.open()
79
75
  }
80
76
 
81
77
  onMounted(() => {
@@ -88,55 +84,47 @@ onUnmounted(() => {
88
84
  </script>
89
85
 
90
86
  <template>
91
- <VDialog v-model="dialog" max-width="800" absolute @click:outside="close">
92
- <VCard>
93
- <VToolbar class="px-6" density="compact">
94
- <span class="headline">{{ ucFirst(t('dialog.image.title')) }}</span>
95
-
96
- <VSpacer />
97
-
98
- <VBtn class="mx-0" icon @click="close">
99
- <VIcon :icon="mdi.mdiClose" />
100
- </VBtn>
101
- </VToolbar>
102
-
87
+ <Dialog ref="dialog" module="image" :max-width="800">
88
+ <template #content>
103
89
  <VCardText>
104
90
  <VRow>
105
91
  <VCol cols="12">
106
- <VTextField v-model="attrs.src" :variant="variantField" :label="ucFirst(t('dialog.image.src'))" />
92
+ <VTextField v-model="attrs.src" density="compact" variant="outlined" :label="t('dialog.image.src')" />
107
93
  </VCol>
108
94
 
109
95
  <VCol cols="12" md="6">
110
- <VTextField v-model="attrs.alt" :variant="variantField" :label="ucFirst(t('dialog.image.alt'))" />
96
+ <VTextField v-model="attrs.alt" density="compact" variant="outlined" :label="t('dialog.image.alt')" />
111
97
  </VCol>
112
98
 
113
99
  <VCol cols="12" md="3">
114
- <VTextField v-model="attrs.width" type="number" :variant="variantField" :precision="0" :min="1" :label="ucFirst(t('dialog.image.width'))" />
100
+ <VTextField v-model="attrs.width" type="number" density="compact" variant="outlined" :precision="0" :min="1" :label="t('dialog.image.width')" />
115
101
  </VCol>
116
102
 
117
103
  <VCol cols="12" md="3">
118
- <VTextField v-model="attrs.height" type="number" :variant="variantField" :precision="0" :min="1" :label="ucFirst(t('dialog.image.height'))" />
104
+ <VTextField v-model="attrs.height" type="number" density="compact" variant="outlined" :precision="0" :min="1" :label="t('dialog.image.height')" />
119
105
  </VCol>
120
106
  </VRow>
121
107
  </VCardText>
108
+ </template>
122
109
 
110
+ <template #actions>
123
111
  <VCardActions>
124
112
  <VRow>
125
113
  <VCol class="d-flex justify-start">
126
114
  <VBtn color="warning" v-if="editor.isActive('image')" :variant="variantBtn" :disabled="isDisabled" @click="clear">
127
- {{ ucFirst(t('dialog.clear')) }}
115
+ {{ t('dialog.clear') }}
128
116
  </VBtn>
129
117
  </VCol>
130
118
  <VCol class="d-flex justify-end">
131
119
  <VBtn :variant="variantBtn" @click="close" class="mr-2">
132
- {{ ucFirst(t('dialog.close')) }}
120
+ {{ t('dialog.close') }}
133
121
  </VBtn>
134
122
  <VBtn color="primary" :variant="variantBtn" :disabled="isDisabled" @click="apply">
135
- {{ ucFirst(t('dialog.apply')) }}
123
+ {{ t('dialog.apply') }}
136
124
  </VBtn>
137
125
  </VCol>
138
126
  </VRow>
139
127
  </VCardActions>
140
- </VCard>
141
- </VDialog>
128
+ </template>
129
+ </Dialog>
142
130
  </template>