tiptapify 0.2.4 → 0.2.6

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 (65) hide show
  1. package/README.md +1 -1
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/tiptapify.mjs +74210 -54575
  4. package/dist/tiptapify.umd.js +87 -84
  5. package/index.d.ts +42 -2
  6. package/package.json +45 -45
  7. package/src/components/Tiptapify.vue +108 -9
  8. package/src/components/Toolbar/Index.vue +2 -2
  9. package/src/components/Toolbar/Items.vue +9 -2
  10. package/src/components/UI/TiptapifyDialog.vue +7 -1
  11. package/src/extensions/components/ai/Button.vue +1 -1
  12. package/src/extensions/components/ai/Dialog.vue +338 -27
  13. package/src/extensions/components/ai/backend.test.ts +314 -0
  14. package/src/extensions/components/ai/backend.ts +303 -0
  15. package/src/extensions/components/ai/charLimit.test.ts +55 -0
  16. package/src/extensions/components/ai/charLimit.ts +30 -0
  17. package/src/extensions/components/ai/characterCount.test.ts +27 -0
  18. package/src/extensions/components/media/iframe/Button.vue +1 -2
  19. package/src/extensions/components/media/iframe/IframeDialog.vue +36 -31
  20. package/src/extensions/components/media/image/Button.vue +1 -1
  21. package/src/extensions/components/media/link/Button.vue +1 -1
  22. package/src/extensions/components/media/link/LinkDialog.vue +19 -36
  23. package/src/extensions/components/media/video/Button.vue +1 -1
  24. package/src/extensions/components/media/video/VideoDialog.vue +17 -17
  25. package/src/extensions/components/misc/source/Button.vue +1 -1
  26. package/src/i18n/locales/ar.json +165 -159
  27. package/src/i18n/locales/bg.json +212 -0
  28. package/src/i18n/locales/ch.json +165 -159
  29. package/src/i18n/locales/cz.json +165 -159
  30. package/src/i18n/locales/de.json +165 -159
  31. package/src/i18n/locales/el.json +212 -0
  32. package/src/i18n/locales/en.json +166 -159
  33. package/src/i18n/locales/es.json +165 -159
  34. package/src/i18n/locales/et.json +212 -0
  35. package/src/i18n/locales/fi.json +165 -159
  36. package/src/i18n/locales/fr.json +165 -159
  37. package/src/i18n/locales/he.json +212 -0
  38. package/src/i18n/locales/hi.json +212 -0
  39. package/src/i18n/locales/hr.json +212 -0
  40. package/src/i18n/locales/hu.json +165 -159
  41. package/src/i18n/locales/id.json +212 -0
  42. package/src/i18n/locales/it.json +165 -159
  43. package/src/i18n/locales/ja.json +165 -159
  44. package/src/i18n/locales/ko.json +165 -159
  45. package/src/i18n/locales/la.json +165 -159
  46. package/src/i18n/locales/lt.json +165 -159
  47. package/src/i18n/locales/nl.json +165 -159
  48. package/src/i18n/locales/no.json +212 -0
  49. package/src/i18n/locales/pl.json +165 -159
  50. package/src/i18n/locales/pt-BR.json +212 -0
  51. package/src/i18n/locales/pt.json +165 -159
  52. package/src/i18n/locales/ro.json +212 -0
  53. package/src/i18n/locales/ru.json +165 -159
  54. package/src/i18n/locales/se.json +165 -159
  55. package/src/i18n/locales/sk.json +212 -0
  56. package/src/i18n/locales/sl.json +212 -0
  57. package/src/i18n/locales/sr.json +212 -0
  58. package/src/i18n/locales/th.json +165 -159
  59. package/src/i18n/locales/tr.json +165 -159
  60. package/src/i18n/locales/uk.json +165 -159
  61. package/src/i18n/locales/vi.json +165 -159
  62. package/src/index.ts +7 -0
  63. package/src/types/editor.ts +40 -2
  64. package/src/utils/validateHref.test.ts +68 -0
  65. package/src/utils/validateHref.ts +21 -0
package/index.d.ts CHANGED
@@ -97,10 +97,17 @@ export interface TiptapifyAiRequest {
97
97
  model?: string
98
98
  messages: TiptapifyAiChatMessage[]
99
99
  temperature?: number
100
- stream?: false
100
+ stream?: boolean
101
101
  [key: string]: unknown
102
102
  }
103
103
 
104
+ export type TiptapifyAiReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max'
105
+
106
+ export interface TiptapifyAiReasoningEffortOptions {
107
+ options: TiptapifyAiReasoningEffort[]
108
+ default?: TiptapifyAiReasoningEffort
109
+ }
110
+
104
111
  export interface TiptapifyAiResponse {
105
112
  content: string
106
113
  }
@@ -114,10 +121,37 @@ export interface TiptapifyAiOpenAiResponse {
114
121
  }>
115
122
  }
116
123
 
117
- export type TiptapifyAiProvider = (request: TiptapifyAiRequest, context: TiptapifyAiEditorContext) => Promise<TiptapifyAiResponse | TiptapifyAiOpenAiResponse | string>
124
+ export interface TiptapifyAiStream {
125
+ signal: AbortSignal
126
+ onChunk: (chunk: string) => void
127
+ onReasoning: (chunk: string) => void
128
+ }
129
+
130
+ export type TiptapifyAiProvider = (
131
+ request: TiptapifyAiRequest,
132
+ context: TiptapifyAiEditorContext,
133
+ stream?: TiptapifyAiStream,
134
+ ) => Promise<TiptapifyAiResponse | TiptapifyAiOpenAiResponse | string>
118
135
 
119
136
  export type TiptapifyAiTokenProvider = () => Promise<string | null> | string | null
120
137
 
138
+ export interface TiptapifyAiBackendRequest {
139
+ prompt: string
140
+ instruction: string
141
+ stream?: boolean
142
+ thinking?: boolean
143
+ reasoning_effort?: TiptapifyAiReasoningEffort
144
+ model?: string
145
+ }
146
+
147
+ export interface TiptapifyAiBackendProviderOptions {
148
+ endpoint: string
149
+ headers?: Record<string, string>
150
+ tokenProvider?: TiptapifyAiTokenProvider
151
+ }
152
+
153
+ export declare function createAiBackendProvider(options: TiptapifyAiBackendProviderOptions): TiptapifyAiProvider
154
+
121
155
  export interface TiptapifyAiStorage {
122
156
  getItem: (key: string) => string | null | Promise<string | null>
123
157
  setItem: (key: string, value: string) => void | Promise<void>
@@ -126,12 +160,18 @@ export interface TiptapifyAiStorage {
126
160
 
127
161
  export interface TiptapifyAiOptions {
128
162
  aiProvider?: TiptapifyAiProvider
163
+ aiEndpoint?: string
164
+ aiHeaders?: Record<string, string>
129
165
  model?: string
130
166
  promptExamples?: TiptapifyAiPromptExample[]
131
167
  mode?: TiptapifyAiMode
132
168
  defaultPrompt?: string
133
169
  systemPrompt?: string
134
170
  temperature?: number
171
+ stream?: boolean
172
+ thinking?: boolean
173
+ reasoningEffort?: TiptapifyAiReasoningEffortOptions
174
+ showReasoning?: boolean
135
175
  chatCompletionOptions?: Record<string, unknown>
136
176
  createMessages?: (context: TiptapifyAiEditorContext) => TiptapifyAiChatMessage[]
137
177
  tokenProvider?: TiptapifyAiTokenProvider
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tiptapify",
3
3
  "types": "./index.d.ts",
4
- "version": "0.2.4",
4
+ "version": "0.2.6",
5
5
  "description": "Tiptap3 editor with Vuetify3 menu implementation",
6
6
  "exports": {
7
7
  ".": {
@@ -70,47 +70,47 @@
70
70
  "packageManager": "pnpm@11.8.0",
71
71
  "dependencies": {
72
72
  "@floating-ui/dom": "^1.7.6",
73
- "@tiptap/core": "^3.27.1",
74
- "@tiptap/extension-blockquote": "^3.27.1",
75
- "@tiptap/extension-bold": "^3.27.1",
76
- "@tiptap/extension-bubble-menu": "^3.27.1",
77
- "@tiptap/extension-code": "^3.27.1",
78
- "@tiptap/extension-code-block": "^3.27.1",
79
- "@tiptap/extension-code-block-lowlight": "^3.27.1",
80
- "@tiptap/extension-color": "^3.27.1",
81
- "@tiptap/extension-document": "^3.27.1",
82
- "@tiptap/extension-floating-menu": "^3.27.1",
83
- "@tiptap/extension-font-family": "^3.27.1",
84
- "@tiptap/extension-hard-break": "^3.27.1",
85
- "@tiptap/extension-heading": "^3.27.1",
86
- "@tiptap/extension-highlight": "^3.27.1",
87
- "@tiptap/extension-horizontal-rule": "^3.27.1",
88
- "@tiptap/extension-image": "^3.27.1",
89
- "@tiptap/extension-invisible-characters": "^3.27.1",
90
- "@tiptap/extension-italic": "^3.27.1",
91
- "@tiptap/extension-link": "^3.27.1",
92
- "@tiptap/extension-list": "^3.27.1",
93
- "@tiptap/extension-list-item": "^3.27.1",
94
- "@tiptap/extension-paragraph": "^3.27.1",
95
- "@tiptap/extension-placeholder": "^3.27.1",
96
- "@tiptap/extension-strike": "^3.27.1",
97
- "@tiptap/extension-subscript": "^3.27.1",
98
- "@tiptap/extension-superscript": "^3.27.1",
99
- "@tiptap/extension-table": "^3.27.1",
100
- "@tiptap/extension-task-item": "^3.27.1",
101
- "@tiptap/extension-task-list": "^3.27.1",
102
- "@tiptap/extension-text": "^3.27.1",
103
- "@tiptap/extension-text-align": "^3.27.1",
104
- "@tiptap/extension-text-style": "^3.27.1",
105
- "@tiptap/extension-typography": "^3.27.1",
106
- "@tiptap/extension-underline": "^3.27.1",
107
- "@tiptap/extension-youtube": "^3.27.1",
108
- "@tiptap/extensions": "^3.27.1",
109
- "@tiptap/pm": "^3.27.1",
110
- "@tiptap/suggestion": "^3.27.1",
111
- "@tiptap/vue-3": "^3.27.1",
73
+ "@tiptap/core": "^3.31.0",
74
+ "@tiptap/extension-blockquote": "^3.31.0",
75
+ "@tiptap/extension-bold": "^3.31.0",
76
+ "@tiptap/extension-bubble-menu": "^3.31.0",
77
+ "@tiptap/extension-code": "^3.31.0",
78
+ "@tiptap/extension-code-block": "^3.31.0",
79
+ "@tiptap/extension-code-block-lowlight": "^3.31.0",
80
+ "@tiptap/extension-color": "^3.31.0",
81
+ "@tiptap/extension-document": "^3.31.0",
82
+ "@tiptap/extension-floating-menu": "^3.31.0",
83
+ "@tiptap/extension-font-family": "^3.31.0",
84
+ "@tiptap/extension-hard-break": "^3.31.0",
85
+ "@tiptap/extension-heading": "^3.31.0",
86
+ "@tiptap/extension-highlight": "^3.31.0",
87
+ "@tiptap/extension-horizontal-rule": "^3.31.0",
88
+ "@tiptap/extension-image": "^3.31.0",
89
+ "@tiptap/extension-invisible-characters": "^3.31.0",
90
+ "@tiptap/extension-italic": "^3.31.0",
91
+ "@tiptap/extension-link": "^3.31.0",
92
+ "@tiptap/extension-list": "^3.31.0",
93
+ "@tiptap/extension-list-item": "^3.31.0",
94
+ "@tiptap/extension-paragraph": "^3.31.0",
95
+ "@tiptap/extension-placeholder": "^3.31.0",
96
+ "@tiptap/extension-strike": "^3.31.0",
97
+ "@tiptap/extension-subscript": "^3.31.0",
98
+ "@tiptap/extension-superscript": "^3.31.0",
99
+ "@tiptap/extension-table": "^3.31.0",
100
+ "@tiptap/extension-task-item": "^3.31.0",
101
+ "@tiptap/extension-task-list": "^3.31.0",
102
+ "@tiptap/extension-text": "^3.31.0",
103
+ "@tiptap/extension-text-align": "^3.31.0",
104
+ "@tiptap/extension-text-style": "^3.31.0",
105
+ "@tiptap/extension-typography": "^3.31.0",
106
+ "@tiptap/extension-underline": "^3.31.0",
107
+ "@tiptap/extension-youtube": "^3.31.0",
108
+ "@tiptap/extensions": "^3.31.0",
109
+ "@tiptap/pm": "^3.31.0",
110
+ "@tiptap/suggestion": "^3.31.0",
111
+ "@tiptap/vue-3": "^3.31.0",
112
112
  "emoji.json": "^16.0.0",
113
- "highlight.js": "^11.11.1",
113
+ "highlight.js": "^11.12.0",
114
114
  "linkifyjs": "^4.3.3",
115
115
  "lowlight": "^3.3.0"
116
116
  },
@@ -142,11 +142,11 @@
142
142
  "typescript": "^6.0.3",
143
143
  "typescript-eslint": "^8.61.1",
144
144
  "unplugin-vue-components": "^32.1.0",
145
- "vite": "^8.0.16",
145
+ "vite": "^8.2.2",
146
146
  "vite-plugin-vuetify": "^2.1.3",
147
- "vite-svg-loader": "^5.1.1",
148
- "vitest": "^4.1.9",
147
+ "vite-svg-loader": "^5.1.3",
148
+ "vitest": "^4.1.11",
149
149
  "vue-eslint-parser": "^10.4.1",
150
- "vue-tsc": "^3.3.5"
150
+ "vue-tsc": "^3.3.11"
151
151
  }
152
152
  }
@@ -6,20 +6,22 @@ import { SlashCommandsConfig } from '@tiptapify/types/slashCommandsTypes'
6
6
  import { computed, onBeforeUnmount, PropType, provide, ref, ShallowRef } from 'vue'
7
7
  import { default as Toolbar } from '@tiptapify/components/Toolbar/Index.vue'
8
8
  import { Editor, EditorContent } from '@tiptap/vue-3'
9
- import { TiptapifyAiOptions, TiptapifyEditor, TiptapifyFooterAlignment, variantBtnTypes, variantFieldTypes } from '@tiptapify/types/editor'
9
+ import { TiptapifyAiOptions, TiptapifyAiResolvedOptions, TiptapifyEditor, TiptapifyFooterAlignment, variantBtnTypes, variantFieldTypes } from '@tiptapify/types/editor'
10
10
  import MenuBubble from '@tiptapify/components/MenuBubble.vue'
11
11
  import MenuFloating from '@tiptapify/components/MenuFloating.vue'
12
12
 
13
13
  import { useI18n } from 'vue-i18n'
14
14
 
15
15
  import { getTiptapEditor } from '@tiptapify/components/index'
16
+ import { createAiBackendProvider } from '@tiptapify/extensions/components/ai/backend'
16
17
 
17
18
  import Footer from '@tiptapify/components/Footer.vue'
18
19
  import { useTheme } from 'vuetify/framework'
19
20
 
20
21
  const props = defineProps({
21
22
  locale: { type: String, default () { return 'en' } },
22
- content: { type: [String, Object] as PropType<string | Record<string, never>>, required: true },
23
+ content: { type: [String, Object] as PropType<string | Record<string, never>>, default () { return '' } },
24
+ modelValue: { type: [String, Object] as PropType<string | Record<string, never>>, default () { return '' } },
23
25
  height: { type: [Number, String], default () { return null } },
24
26
  variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
25
27
  variantField: { type: String as PropType<variantFieldTypes>, default() { return defaults.variantField } },
@@ -48,12 +50,14 @@ const props = defineProps({
48
50
  loadingHeight: { type: String, default() { return '1px' } },
49
51
  })
50
52
 
53
+ const emit = defineEmits(['update:modelValue', 'editor-ready', 'content-changed'])
54
+
51
55
  const loadingProgress = ref(0)
52
56
 
53
57
  const { t } = useI18n()
54
58
 
55
59
  const appTheme = useTheme()
56
- const currentTheme = ref(appTheme.global.name)
60
+ const currentTheme = computed(() => appTheme.name.value)
57
61
 
58
62
  const defaultAiPromptExamples = computed(() => [
59
63
  {
@@ -81,19 +85,42 @@ const tiptapifyAi = computed(() => {
81
85
 
82
86
  const options = props.ai === true ? {} : props.ai
83
87
 
84
- return {
88
+ const resolved: TiptapifyAiResolvedOptions = {
85
89
  ...options,
86
90
  enabled: true,
87
91
  promptExamples: options.promptExamples?.length ? options.promptExamples : defaultAiPromptExamples.value,
88
92
  }
93
+
94
+ // Backend generation: when no `aiProvider` is given but an `aiEndpoint`
95
+ // is set, synthesize a provider that posts the request to the endpoint.
96
+ // An explicit `aiProvider` always wins.
97
+ if (!resolved.aiProvider && resolved.aiEndpoint) {
98
+ resolved.aiProvider = createAiBackendProvider({
99
+ endpoint: resolved.aiEndpoint,
100
+ headers: resolved.aiHeaders,
101
+ tokenProvider: resolved.tokenProvider,
102
+ })
103
+ }
104
+
105
+ return resolved
89
106
  })
90
107
 
91
108
  function contentChanged() {
92
- emit('content-changed', { html: editor.value?.getHTML(), json: editor.value?.getJSON() })
109
+ const html = editor.value?.getHTML() ?? ''
110
+ emit('update:modelValue', html)
111
+ emit('content-changed', { html, json: editor.value?.getJSON() })
112
+ }
113
+
114
+ function onContainerClick(event: MouseEvent) {
115
+ if ((event.target as Element).closest('.ProseMirror')) {
116
+ return
117
+ }
118
+
119
+ editor.value?.chain().focus().run()
93
120
  }
94
121
 
95
122
  const editor: ShallowRef<Editor | undefined> = getTiptapEditor(
96
- props.content,
123
+ props.content || props.modelValue,
97
124
  computed(() => props.placeholder || t('content.placeholder')).value,
98
125
  props.slashCommands,
99
126
  props.customExtensions,
@@ -109,8 +136,6 @@ const editor: ShallowRef<Editor | undefined> = getTiptapEditor(
109
136
  },
110
137
  )
111
138
 
112
- const emit = defineEmits(['update:modelValue', 'editor-ready', 'content-changed'])
113
-
114
139
  provide('tiptapifyEditor', editor)
115
140
  provide('tiptapifyI18n', { t })
116
141
  provide('tiptapifyAi', tiptapifyAi)
@@ -150,7 +175,7 @@ onBeforeUnmount(() => {
150
175
 
151
176
  <VProgressLinear v-model="loadingProgress" :color="loadingColor" :height="loadingHeight" :indeterminate="loading" />
152
177
 
153
- <div class="pa-2 tiptapify-container resizable" :style="computeResizableHeight">
178
+ <div class="pa-2 tiptapify-container resizable" :style="computeResizableHeight" @click="onContainerClick">
154
179
  <MenuFloating v-if="floatingMenu" :variant="variantBtn" :theme="currentTheme" />
155
180
 
156
181
  <MenuBubble v-if="bubbleMenu" :variant="variantBtn" :theme="currentTheme" />
@@ -197,6 +222,7 @@ onBeforeUnmount(() => {
197
222
  --yellow: rgba(250, 204, 21, .4);
198
223
  --yellow-light: #FFFAE5;
199
224
  --red: #FF5C33;
225
+ --red-soft: #B24A40;
200
226
  --red-light: #FFEBE5;
201
227
  --shadow: 0px 12px 33px 0px rgba(0, 0, 0, .06), 0px 3.618px 9.949px 0px rgba(0, 0, 0, .04);
202
228
  --border: 1px solid var(--gray-2);
@@ -207,6 +233,21 @@ onBeforeUnmount(() => {
207
233
  overflow: auto;
208
234
  }
209
235
 
236
+ .tiptapify-container {
237
+ display: flex;
238
+ flex-direction: column;
239
+ }
240
+
241
+ .tiptapify-container .tiptapify-editor {
242
+ display: flex;
243
+ flex: 1;
244
+ flex-direction: column;
245
+ }
246
+
247
+ .tiptapify-container .tiptapify-editor > .ProseMirror {
248
+ flex: 1;
249
+ }
250
+
210
251
  /* Basic editor styles */
211
252
  .tiptap {
212
253
  :first-child {
@@ -560,4 +601,62 @@ onBeforeUnmount(() => {
560
601
  }
561
602
  }
562
603
  }
604
+
605
+ /*
606
+ * Dialog layout primitives.
607
+ *
608
+ * Dialogs lay their fields out with a self-contained 12-column grid instead
609
+ * of VRow/VCol. The bundled Vuetify 3 components emit v3 grid classes
610
+ * (.v-col-*, .v-col-md-*), but Vuetify 4 renamed them (.v-col--cols-*), so
611
+ * the consumer's Vuetify stylesheet does not size the columns and every
612
+ * field collapses onto a single row. Keeping the layout inside tiptapify
613
+ * makes it work with Vuetify 3 and 4 alike, regardless of the CSS the
614
+ * consumer loads.
615
+ *
616
+ * The 960px breakpoint preserves the Vuetify 3 "md" threshold
617
+ * (Vuetify 4 lowered it to 840px).
618
+ */
619
+ .tiptapify-dialog-grid {
620
+ display: grid;
621
+ gap: 24px;
622
+ grid-template-columns: repeat(12, minmax(0, 1fr));
623
+
624
+ > .tiptapify-dialog-col {
625
+ grid-column: 1 / -1;
626
+ min-width: 0;
627
+ }
628
+
629
+ @media (min-width: 960px) {
630
+ > .tiptapify-dialog-col--3 {
631
+ grid-column: span 3;
632
+ }
633
+
634
+ > .tiptapify-dialog-col--4 {
635
+ grid-column: span 4;
636
+ }
637
+
638
+ > .tiptapify-dialog-col--6 {
639
+ grid-column: span 6;
640
+ }
641
+
642
+ > .tiptapify-dialog-col--8 {
643
+ grid-column: span 8;
644
+ }
645
+ }
646
+ }
647
+
648
+ .tiptapify-dialog-actions {
649
+ display: flex;
650
+ flex-wrap: wrap;
651
+ align-items: center;
652
+ justify-content: space-between;
653
+ gap: 8px 16px;
654
+
655
+ > .tiptapify-dialog-actions__start,
656
+ > .tiptapify-dialog-actions__end {
657
+ display: flex;
658
+ align-items: center;
659
+ gap: 8px;
660
+ }
661
+ }
563
662
  </style>
@@ -178,10 +178,10 @@ Object.keys(props.customExtensions).forEach((key: any) => {
178
178
  <div v-if="editor" class="tiptapify-toolbar">
179
179
  <VToolbar elevation="1" :theme="theme" height="auto" :class="`ps-1 pr-1 rounded-t-${rounded}`">
180
180
  <VSlideGroup v-if="toolbarScrollable">
181
- <Items :items="toolbarItems" />
181
+ <Items :items="toolbarItems" :variant-btn="variantBtn" />
182
182
  </VSlideGroup>
183
183
 
184
- <Items v-else :items="toolbarItems" />
184
+ <Items v-else :items="toolbarItems" :variant-btn="variantBtn" />
185
185
  </VToolbar>
186
186
  </div>
187
187
  </template>
@@ -20,9 +20,9 @@ defineProps({
20
20
  <div class="menu-divider" />
21
21
  </template>
22
22
  <template v-else>
23
- <VBtnGroup v-if="item.group" elevation="4">
23
+ <VBtnGroup v-if="item.group" elevation="4" :class="{ 'tiptapify-btn-group--elevated': variantBtn === 'elevated' }">
24
24
  <template v-for="sectionItem in item.components" :key="sectionItem.name">
25
- <component :is="sectionItem.component" v-bind="{ ...sectionItem.props ?? {} }" />
25
+ <component :is="sectionItem.component" v-bind="{ variantBtn, ...sectionItem.props ?? {} }" />
26
26
  </template>
27
27
  </VBtnGroup>
28
28
  <template v-else>
@@ -40,6 +40,13 @@ defineProps({
40
40
  </template>
41
41
 
42
42
  <style lang="scss" scoped>
43
+ .tiptapify-btn-group--elevated {
44
+ box-shadow:
45
+ 0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, 0.2)),
46
+ 0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, 0.14)),
47
+ 0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, 0.12));
48
+ }
49
+
43
50
  :deep(.v-btn-group) {
44
51
  height: 32px !important;
45
52
  }
@@ -144,7 +144,8 @@ onBeforeUnmount(() => {
144
144
  <VCard>
145
145
  <VCardTitle
146
146
  ref="movableHandler"
147
- :class="`d-flex ${!fullscreen ? 'tiptapify-movable-handler' : ''}`"
147
+ class="tiptapify-dialog-header"
148
+ :class="!fullscreen ? 'tiptapify-movable-handler' : ''"
148
149
  style="user-select: none;"
149
150
  >
150
151
  <VLabel>
@@ -168,6 +169,11 @@ onBeforeUnmount(() => {
168
169
  </template>
169
170
 
170
171
  <style lang="scss" scoped>
172
+ .tiptapify-dialog-header {
173
+ align-items: center;
174
+ display: flex;
175
+ }
176
+
171
177
  :deep(.v-overlay__content) {
172
178
  position: fixed;
173
179
  }
@@ -38,5 +38,5 @@ function showDialog() {
38
38
  <BtnIcon :icon="icon" />
39
39
  </VBtn>
40
40
 
41
- <AiDialog ref="dialog" />
41
+ <AiDialog ref="dialog" :variant-btn="variantBtn" />
42
42
  </template>