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.
- package/README.md +1 -1
- package/dist/tiptapify.css +1 -1
- package/dist/tiptapify.mjs +74210 -54575
- package/dist/tiptapify.umd.js +87 -84
- package/index.d.ts +42 -2
- package/package.json +45 -45
- package/src/components/Tiptapify.vue +108 -9
- package/src/components/Toolbar/Index.vue +2 -2
- package/src/components/Toolbar/Items.vue +9 -2
- package/src/components/UI/TiptapifyDialog.vue +7 -1
- package/src/extensions/components/ai/Button.vue +1 -1
- package/src/extensions/components/ai/Dialog.vue +338 -27
- package/src/extensions/components/ai/backend.test.ts +314 -0
- package/src/extensions/components/ai/backend.ts +303 -0
- package/src/extensions/components/ai/charLimit.test.ts +55 -0
- package/src/extensions/components/ai/charLimit.ts +30 -0
- package/src/extensions/components/ai/characterCount.test.ts +27 -0
- package/src/extensions/components/media/iframe/Button.vue +1 -2
- package/src/extensions/components/media/iframe/IframeDialog.vue +36 -31
- package/src/extensions/components/media/image/Button.vue +1 -1
- package/src/extensions/components/media/link/Button.vue +1 -1
- package/src/extensions/components/media/link/LinkDialog.vue +19 -36
- package/src/extensions/components/media/video/Button.vue +1 -1
- package/src/extensions/components/media/video/VideoDialog.vue +17 -17
- package/src/extensions/components/misc/source/Button.vue +1 -1
- package/src/i18n/locales/ar.json +165 -159
- package/src/i18n/locales/bg.json +212 -0
- package/src/i18n/locales/ch.json +165 -159
- package/src/i18n/locales/cz.json +165 -159
- package/src/i18n/locales/de.json +165 -159
- package/src/i18n/locales/el.json +212 -0
- package/src/i18n/locales/en.json +166 -159
- package/src/i18n/locales/es.json +165 -159
- package/src/i18n/locales/et.json +212 -0
- package/src/i18n/locales/fi.json +165 -159
- package/src/i18n/locales/fr.json +165 -159
- package/src/i18n/locales/he.json +212 -0
- package/src/i18n/locales/hi.json +212 -0
- package/src/i18n/locales/hr.json +212 -0
- package/src/i18n/locales/hu.json +165 -159
- package/src/i18n/locales/id.json +212 -0
- package/src/i18n/locales/it.json +165 -159
- package/src/i18n/locales/ja.json +165 -159
- package/src/i18n/locales/ko.json +165 -159
- package/src/i18n/locales/la.json +165 -159
- package/src/i18n/locales/lt.json +165 -159
- package/src/i18n/locales/nl.json +165 -159
- package/src/i18n/locales/no.json +212 -0
- package/src/i18n/locales/pl.json +165 -159
- package/src/i18n/locales/pt-BR.json +212 -0
- package/src/i18n/locales/pt.json +165 -159
- package/src/i18n/locales/ro.json +212 -0
- package/src/i18n/locales/ru.json +165 -159
- package/src/i18n/locales/se.json +165 -159
- package/src/i18n/locales/sk.json +212 -0
- package/src/i18n/locales/sl.json +212 -0
- package/src/i18n/locales/sr.json +212 -0
- package/src/i18n/locales/th.json +165 -159
- package/src/i18n/locales/tr.json +165 -159
- package/src/i18n/locales/uk.json +165 -159
- package/src/i18n/locales/vi.json +165 -159
- package/src/index.ts +7 -0
- package/src/types/editor.ts +40 -2
- package/src/utils/validateHref.test.ts +68 -0
- 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?:
|
|
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
|
|
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
|
+
"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.
|
|
74
|
-
"@tiptap/extension-blockquote": "^3.
|
|
75
|
-
"@tiptap/extension-bold": "^3.
|
|
76
|
-
"@tiptap/extension-bubble-menu": "^3.
|
|
77
|
-
"@tiptap/extension-code": "^3.
|
|
78
|
-
"@tiptap/extension-code-block": "^3.
|
|
79
|
-
"@tiptap/extension-code-block-lowlight": "^3.
|
|
80
|
-
"@tiptap/extension-color": "^3.
|
|
81
|
-
"@tiptap/extension-document": "^3.
|
|
82
|
-
"@tiptap/extension-floating-menu": "^3.
|
|
83
|
-
"@tiptap/extension-font-family": "^3.
|
|
84
|
-
"@tiptap/extension-hard-break": "^3.
|
|
85
|
-
"@tiptap/extension-heading": "^3.
|
|
86
|
-
"@tiptap/extension-highlight": "^3.
|
|
87
|
-
"@tiptap/extension-horizontal-rule": "^3.
|
|
88
|
-
"@tiptap/extension-image": "^3.
|
|
89
|
-
"@tiptap/extension-invisible-characters": "^3.
|
|
90
|
-
"@tiptap/extension-italic": "^3.
|
|
91
|
-
"@tiptap/extension-link": "^3.
|
|
92
|
-
"@tiptap/extension-list": "^3.
|
|
93
|
-
"@tiptap/extension-list-item": "^3.
|
|
94
|
-
"@tiptap/extension-paragraph": "^3.
|
|
95
|
-
"@tiptap/extension-placeholder": "^3.
|
|
96
|
-
"@tiptap/extension-strike": "^3.
|
|
97
|
-
"@tiptap/extension-subscript": "^3.
|
|
98
|
-
"@tiptap/extension-superscript": "^3.
|
|
99
|
-
"@tiptap/extension-table": "^3.
|
|
100
|
-
"@tiptap/extension-task-item": "^3.
|
|
101
|
-
"@tiptap/extension-task-list": "^3.
|
|
102
|
-
"@tiptap/extension-text": "^3.
|
|
103
|
-
"@tiptap/extension-text-align": "^3.
|
|
104
|
-
"@tiptap/extension-text-style": "^3.
|
|
105
|
-
"@tiptap/extension-typography": "^3.
|
|
106
|
-
"@tiptap/extension-underline": "^3.
|
|
107
|
-
"@tiptap/extension-youtube": "^3.
|
|
108
|
-
"@tiptap/extensions": "^3.
|
|
109
|
-
"@tiptap/pm": "^3.
|
|
110
|
-
"@tiptap/suggestion": "^3.
|
|
111
|
-
"@tiptap/vue-3": "^3.
|
|
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.
|
|
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.
|
|
145
|
+
"vite": "^8.2.2",
|
|
146
146
|
"vite-plugin-vuetify": "^2.1.3",
|
|
147
|
-
"vite-svg-loader": "^5.1.
|
|
148
|
-
"vitest": "^4.1.
|
|
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.
|
|
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>>,
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|