tiptapify 0.2.6 → 0.3.1

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 (71) hide show
  1. package/README.md +1 -1
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/tiptapify.mjs +23430 -25369
  4. package/dist/tiptapify.umd.js +70 -73
  5. package/index.d.ts +5 -0
  6. package/package.json +1 -1
  7. package/src/components/Footer.vue +1 -1
  8. package/src/components/Tiptapify.vue +6 -2
  9. package/src/components/Toolbar/Index.vue +3 -4
  10. package/src/components/Toolbar/Items.test.ts +53 -0
  11. package/src/components/Toolbar/Items.vue +5 -5
  12. package/src/components/UI/HotkeyTooltip.test.ts +65 -0
  13. package/src/components/UI/HotkeyTooltip.vue +54 -0
  14. package/src/components/UI/Tooltip.vue +20 -0
  15. package/src/composables/useTiptapifyConfig.test.ts +66 -0
  16. package/src/composables/useTiptapifyConfig.ts +17 -0
  17. package/src/constants/defaults.ts +4 -2
  18. package/src/extensions/components/actions/redo/Button.vue +5 -9
  19. package/src/extensions/components/actions/undo/Button.vue +5 -9
  20. package/src/extensions/components/ai/Button.vue +7 -10
  21. package/src/extensions/components/ai/Dialog.vue +4 -9
  22. package/src/extensions/components/alignment/center/Button.vue +5 -9
  23. package/src/extensions/components/alignment/justify/Button.vue +5 -9
  24. package/src/extensions/components/alignment/left/Button.vue +5 -9
  25. package/src/extensions/components/alignment/right/Button.vue +5 -9
  26. package/src/extensions/components/format/bold/Button.vue +5 -9
  27. package/src/extensions/components/format/italic/Button.vue +5 -9
  28. package/src/extensions/components/format/strike/Button.vue +5 -9
  29. package/src/extensions/components/format/underline/Button.vue +5 -9
  30. package/src/extensions/components/formatExtra/code/Button.vue +5 -9
  31. package/src/extensions/components/formatExtra/codeBlock/Button.vue +5 -9
  32. package/src/extensions/components/formatExtra/quote/Button.vue +5 -9
  33. package/src/extensions/components/formatExtra/sub/Button.vue +5 -9
  34. package/src/extensions/components/formatExtra/sup/Button.vue +5 -9
  35. package/src/extensions/components/list/bullet/Button.vue +8 -13
  36. package/src/extensions/components/list/indent/Button.vue +5 -9
  37. package/src/extensions/components/list/numbered/Button.vue +5 -9
  38. package/src/extensions/components/list/outdent/Button.vue +5 -9
  39. package/src/extensions/components/list/task/Button.vue +5 -9
  40. package/src/extensions/components/media/charmap/Button.vue +5 -8
  41. package/src/extensions/components/media/charmap/Picker.vue +2 -3
  42. package/src/extensions/components/media/emoji/Button.vue +6 -9
  43. package/src/extensions/components/media/emoji/Picker.vue +2 -3
  44. package/src/extensions/components/media/iframe/Button.vue +6 -10
  45. package/src/extensions/components/media/iframe/IframeDialog.vue +3 -7
  46. package/src/extensions/components/media/image/Button.vue +6 -10
  47. package/src/extensions/components/media/image/ImageDialog.vue +5 -10
  48. package/src/extensions/components/media/link/Button.vue +7 -10
  49. package/src/extensions/components/media/link/LinkDialog.vue +3 -7
  50. package/src/extensions/components/media/table/Button.vue +10 -24
  51. package/src/extensions/components/media/table/ColumnActions.vue +4 -9
  52. package/src/extensions/components/media/table/RowActions.vue +4 -9
  53. package/src/extensions/components/media/video/Button.vue +6 -10
  54. package/src/extensions/components/media/video/VideoDialog.vue +3 -7
  55. package/src/extensions/components/misc/break/Button.vue +5 -9
  56. package/src/extensions/components/misc/formatClear/Button.vue +5 -9
  57. package/src/extensions/components/misc/fullscreen/Button.vue +5 -9
  58. package/src/extensions/components/misc/invisibleChar/Button.vue +5 -9
  59. package/src/extensions/components/misc/line/Button.vue +5 -9
  60. package/src/extensions/components/misc/preview/Button.vue +5 -9
  61. package/src/extensions/components/misc/source/Button.vue +6 -10
  62. package/src/extensions/components/misc/source/ShowSourceDialog.vue +4 -5
  63. package/src/extensions/components/style/color/Button.vue +5 -9
  64. package/src/extensions/components/style/fontFamily/Button.vue +5 -9
  65. package/src/extensions/components/style/fontSize/Button.vue +6 -7
  66. package/src/extensions/components/style/heading/Button.vue +6 -8
  67. package/src/extensions/components/style/highlight/Button.vue +5 -9
  68. package/src/extensions/components/style/lineHeight/Button.vue +5 -9
  69. package/src/index.ts +3 -0
  70. package/src/utils/hotkeys.test.ts +146 -0
  71. package/src/utils/hotkeys.ts +65 -0
package/index.d.ts CHANGED
@@ -62,6 +62,7 @@ import '@tiptap/extension-invisible-characters'
62
62
 
63
63
  import Tiptapify from './src/components/Tiptapify.vue'
64
64
  import TiptapifyDialog from './src/components/UI/TiptapifyDialog.vue'
65
+ import { TIPTAPIFY_CONFIG_KEY, useTiptapifyConfig, TiptapifyConfig } from './src/composables/useTiptapifyConfig'
65
66
  import * as mdi from '@mdi/js'
66
67
 
67
68
  export type TiptapifyFooterAlignment = 'start' | 'center' | 'end'
@@ -188,6 +189,8 @@ export {
188
189
  mdi,
189
190
  Tiptapify,
190
191
  TiptapifyDialog,
192
+ TIPTAPIFY_CONFIG_KEY,
193
+ useTiptapifyConfig,
191
194
  TiptapEditor,
192
195
  nodeViewProps,
193
196
  NodeViewWrapper,
@@ -225,6 +228,8 @@ export type {
225
228
  SingleCommands,
226
229
  }
227
230
 
231
+ export type { TiptapifyConfig }
232
+
228
233
  declare module '@vue/runtime-core' {
229
234
  interface GlobalComponents {
230
235
  Tiptapify: typeof Tiptapify
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tiptapify",
3
3
  "types": "./index.d.ts",
4
- "version": "0.2.6",
4
+ "version": "0.3.1",
5
5
  "description": "Tiptap3 editor with Vuetify3 menu implementation",
6
6
  "exports": {
7
7
  ".": {
@@ -57,7 +57,7 @@ function showFooter() {
57
57
  <VRow>
58
58
  <VCol class="d-flex align-center" :class="`justify-${alignment}`">
59
59
  <template v-if="limit > 0">
60
- <VTooltip>
60
+ <VTooltip :open-delay="1500">
61
61
  <template #default>
62
62
  <span v-html="limitText" />
63
63
  </template>
@@ -3,7 +3,7 @@
3
3
  import defaults from '@tiptapify/constants/defaults'
4
4
  import { itemsPropType, toolbarSections } from '@tiptapify/types/toolbarTypes'
5
5
  import { SlashCommandsConfig } from '@tiptapify/types/slashCommandsTypes'
6
- import { computed, onBeforeUnmount, PropType, provide, ref, ShallowRef } from 'vue'
6
+ import { computed, onBeforeUnmount, PropType, provide, ref, ShallowRef, toRef } from 'vue'
7
7
  import { default as Toolbar } from '@tiptapify/components/Toolbar/Index.vue'
8
8
  import { Editor, EditorContent } from '@tiptap/vue-3'
9
9
  import { TiptapifyAiOptions, TiptapifyAiResolvedOptions, TiptapifyEditor, TiptapifyFooterAlignment, variantBtnTypes, variantFieldTypes } from '@tiptapify/types/editor'
@@ -13,6 +13,7 @@ import MenuFloating from '@tiptapify/components/MenuFloating.vue'
13
13
  import { useI18n } from 'vue-i18n'
14
14
 
15
15
  import { getTiptapEditor } from '@tiptapify/components/index'
16
+ import { TIPTAPIFY_CONFIG_KEY } from '@tiptapify/composables/useTiptapifyConfig'
16
17
  import { createAiBackendProvider } from '@tiptapify/extensions/components/ai/backend'
17
18
 
18
19
  import Footer from '@tiptapify/components/Footer.vue'
@@ -139,6 +140,10 @@ const editor: ShallowRef<Editor | undefined> = getTiptapEditor(
139
140
  provide('tiptapifyEditor', editor)
140
141
  provide('tiptapifyI18n', { t })
141
142
  provide('tiptapifyAi', tiptapifyAi)
143
+ provide(TIPTAPIFY_CONFIG_KEY, {
144
+ variantBtn: toRef(props, 'variantBtn'),
145
+ variantField: toRef(props, 'variantField'),
146
+ })
142
147
 
143
148
  editor.value?.chain().setFontFamily(props.defaultFontFamily).run()
144
149
 
@@ -162,7 +167,6 @@ onBeforeUnmount(() => {
162
167
  <template v-if="toolbar">
163
168
  <Toolbar
164
169
  v-if="editor"
165
- :variant-btn="variantBtn"
166
170
  :variant-field="variantField"
167
171
  :font-measure="fontMeasure"
168
172
  :items="items"
@@ -2,14 +2,13 @@
2
2
  import { Editor } from '@tiptap/vue-3'
3
3
  import Items from '@tiptapify/components/Toolbar/Items.vue'
4
4
  import defaults from '@tiptapify/constants/defaults'
5
- import { variantBtnTypes, variantFieldTypes } from '@tiptapify/types/editor'
5
+ import { variantFieldTypes } from '@tiptapify/types/editor'
6
6
  import { computed, inject, PropType, Ref } from 'vue'
7
7
  import { itemsPropType, toolbarSections } from '@tiptapify/types/toolbarTypes'
8
8
 
9
9
  import { default as toolbarItemsGroups, availableItems } from '@tiptapify/components/Toolbar/items'
10
10
 
11
11
  const props = defineProps({
12
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
13
12
  variantField: { type: String as PropType<variantFieldTypes>, default() { return defaults.variantField } },
14
13
  items: { type: [Array, Object] as PropType<itemsPropType>, default() { return [] } },
15
14
  itemsExclude: { type: Boolean, default() { return false } },
@@ -178,10 +177,10 @@ Object.keys(props.customExtensions).forEach((key: any) => {
178
177
  <div v-if="editor" class="tiptapify-toolbar">
179
178
  <VToolbar elevation="1" :theme="theme" height="auto" :class="`ps-1 pr-1 rounded-t-${rounded}`">
180
179
  <VSlideGroup v-if="toolbarScrollable">
181
- <Items :items="toolbarItems" :variant-btn="variantBtn" />
180
+ <Items :items="toolbarItems" />
182
181
  </VSlideGroup>
183
182
 
184
- <Items v-else :items="toolbarItems" :variant-btn="variantBtn" />
183
+ <Items v-else :items="toolbarItems" />
185
184
  </VToolbar>
186
185
  </div>
187
186
  </template>
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import { createSSRApp, h, provide, ref } from 'vue'
3
+ import { renderToString } from 'vue/server-renderer'
4
+ import { createVuetify } from 'vuetify'
5
+ import Items from '@tiptapify/components/Toolbar/Items.vue'
6
+ import HeadingButton from '@tiptapify/extensions/components/style/heading/Button.vue'
7
+
8
+ const editor = {
9
+ instanceId: 1,
10
+ isActive: () => false,
11
+ can: () => ({ chain: () => ({ focus: () => ({ toggleHeading: () => ({ run: () => false }) }) }) }),
12
+ chain: () => ({ focus: () => ({ redo: () => ({ run: () => false }) }) }),
13
+ commands: {},
14
+ }
15
+
16
+ const items = [
17
+ {
18
+ section: 'style',
19
+ group: true,
20
+ components: [{ name: 'heading', component: HeadingButton }],
21
+ },
22
+ ]
23
+
24
+ async function renderToolbar () {
25
+ const warnings: string[] = []
26
+ const warn = vi.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
27
+ warnings.push(args.map(String).join(' '))
28
+ })
29
+
30
+ const app = createSSRApp({
31
+ setup () {
32
+ provide('tiptapifyEditor', ref(editor))
33
+ provide('tiptapifyI18n', { t: (key: string) => key })
34
+
35
+ return () => h(Items, { items })
36
+ },
37
+ })
38
+ app.use(createVuetify())
39
+
40
+ const html = await renderToString(app)
41
+ warn.mockRestore()
42
+
43
+ return { html, warnings }
44
+ }
45
+
46
+ describe('Toolbar Items', () => {
47
+ it('does not pass undeclared attributes to toolbar buttons', async () => {
48
+ const { html, warnings } = await renderToolbar()
49
+
50
+ expect(html).toContain('tiptapify-heading-button-1')
51
+ expect(warnings.join('\n')).not.toContain('Extraneous non-props attributes')
52
+ })
53
+ })
@@ -1,16 +1,16 @@
1
1
  <script setup lang="ts">
2
2
 
3
- import defaults from '@tiptapify/constants/defaults'
4
- import { variantBtnTypes } from '@tiptapify/types/editor'
3
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
5
4
  import { PropType } from 'vue'
6
5
 
7
6
  import { toolbarSections } from '@tiptapify/types/toolbarTypes'
8
7
 
9
8
  defineProps({
10
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
11
9
  items: { type: Array as PropType<toolbarSections>, default() { return {} } },
12
10
  })
13
11
 
12
+ const { variantBtn } = useTiptapifyConfig()
13
+
14
14
  </script>
15
15
 
16
16
  <template>
@@ -22,7 +22,7 @@ defineProps({
22
22
  <template v-else>
23
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="{ variantBtn, ...sectionItem.props ?? {} }" />
25
+ <component :is="sectionItem.component" v-bind="sectionItem.props ?? {}" />
26
26
  </template>
27
27
  </VBtnGroup>
28
28
  <template v-else>
@@ -30,7 +30,7 @@ defineProps({
30
30
  :is="sectionItem.component"
31
31
  v-for="sectionItem in item.components"
32
32
  :key="sectionItem.name"
33
- v-bind="{ variantBtn, ...sectionItem.props ?? {} }"
33
+ v-bind="sectionItem.props ?? {}"
34
34
  />
35
35
  </template>
36
36
  <div class="menu-divider" />
@@ -0,0 +1,65 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest'
2
+ import { createSSRApp, h } from 'vue'
3
+ import { renderToString } from 'vue/server-renderer'
4
+ import { createVuetify } from 'vuetify'
5
+ import HotkeyTooltip from './HotkeyTooltip.vue'
6
+
7
+ const MAC_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
8
+ const WIN_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
9
+
10
+ function mockUserAgent (userAgent: string) {
11
+ Object.defineProperty(window.navigator, 'userAgent', {
12
+ value: userAgent,
13
+ configurable: true,
14
+ })
15
+ }
16
+
17
+ function renderTooltip (label: string, hotkey: string): Promise<string> {
18
+ const app = createSSRApp({
19
+ render: () => h(HotkeyTooltip, { label, hotkey })
20
+ })
21
+ app.use(createVuetify())
22
+
23
+ return renderToString(app)
24
+ }
25
+
26
+ describe('HotkeyTooltip', () => {
27
+ afterEach(() => {
28
+ vi.unstubAllGlobals()
29
+ })
30
+
31
+ it('renders label and spelled-out hotkey on two lines on Windows', async () => {
32
+ mockUserAgent(WIN_UA)
33
+ const html = await renderTooltip('Bold', 'Mod-Shift-b')
34
+
35
+ expect(html).toContain('t-hotkey-tooltip__label')
36
+ expect(html).toContain('t-hotkey-tooltip__hotkey')
37
+ expect(html).toContain('Bold')
38
+ expect(html).toContain('Ctrl')
39
+ expect(html).toContain('Shift')
40
+ expect(html).toContain('>B</span>')
41
+ expect(html).not.toContain('mdiSvg:')
42
+ })
43
+
44
+ it('renders the hotkey with icons on macOS without spelled-out names', async () => {
45
+ mockUserAgent(MAC_UA)
46
+ const html = await renderTooltip('Heading', 'Mod-Alt-1..6')
47
+
48
+ expect(html).toContain('t-hotkey-tooltip__label')
49
+ expect(html).toContain('t-hotkey-tooltip__hotkey')
50
+ expect(html).toContain('Heading')
51
+ expect(html).toContain('mdiSvg:')
52
+ expect(html).toContain('1–6')
53
+ expect(html).not.toContain('Ctrl')
54
+ expect(html).not.toContain('>Command<')
55
+ expect(html).not.toContain('>Option<')
56
+ })
57
+
58
+ it('renders Enter as an icon on macOS', async () => {
59
+ mockUserAgent(MAC_UA)
60
+ const html = await renderTooltip('Hard break', 'Mod-Enter')
61
+
62
+ expect(html).toContain('mdiSvg:')
63
+ expect(html).not.toContain('>Enter<')
64
+ })
65
+ })
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+
3
+ import { computed } from 'vue'
4
+ import { hotkeyParts } from '@tiptapify/utils/hotkeys'
5
+
6
+ const props = defineProps({
7
+ label: { type: String, required: true },
8
+ hotkey: { type: String, required: true },
9
+ })
10
+
11
+ const parts = computed(() => hotkeyParts(props.hotkey))
12
+
13
+ </script>
14
+
15
+ <template>
16
+ <span class="t-hotkey-tooltip">
17
+ <span class="t-hotkey-tooltip__label">{{ label }}</span>
18
+ <span class="t-hotkey-tooltip__hotkey">
19
+ <template v-for="(part, index) in parts" :key="index">
20
+ <span v-if="index" class="t-hotkey-sep">+</span>
21
+ <VIcon v-if="part.icon" :icon="part.icon" size="12" class="t-hotkey-icon" />
22
+ <span v-else>{{ part.label }}</span>
23
+ </template>
24
+ </span>
25
+ </span>
26
+ </template>
27
+
28
+ <style scoped lang="scss">
29
+ .t-hotkey-tooltip {
30
+ align-items: center;
31
+ display: flex;
32
+ flex-direction: column;
33
+ gap: 3px;
34
+ padding: 4px 0;
35
+ white-space: nowrap;
36
+ }
37
+
38
+ .t-hotkey-tooltip__hotkey {
39
+ align-items: center;
40
+ background: rgba(127, 127, 127, .2);
41
+ background: color-mix(in srgb, currentColor 14%, transparent);
42
+ border-radius: 4px;
43
+ display: inline-flex;
44
+ font-family: 'JetBrainsMono', ui-monospace, Menlo, Consolas, monospace;
45
+ font-size: 11px;
46
+ gap: 4px;
47
+ letter-spacing: .03em;
48
+ padding: 3px 6px;
49
+
50
+ .t-hotkey-icon {
51
+ font-size: 12px;
52
+ }
53
+ }
54
+ </style>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+
3
+ import HotkeyTooltip from '@tiptapify/components/UI/HotkeyTooltip.vue'
4
+
5
+ defineProps({
6
+ label: { type: String, default: '' },
7
+ hotkey: { type: String, default: '' },
8
+ openDelay: { type: Number, default: 500 },
9
+ })
10
+
11
+ </script>
12
+
13
+ <template>
14
+ <VTooltip activator="parent" :open-delay="openDelay">
15
+ <HotkeyTooltip v-if="hotkey" :label="label" :hotkey="hotkey" />
16
+ <slot v-else>
17
+ {{ label }}
18
+ </slot>
19
+ </VTooltip>
20
+ </template>
@@ -0,0 +1,66 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { createSSRApp, h, provide, ref } from 'vue'
3
+ import { renderToString } from 'vue/server-renderer'
4
+ import { createVuetify } from 'vuetify'
5
+ import BoldButton from '@tiptapify/extensions/components/format/bold/Button.vue'
6
+ import { TIPTAPIFY_CONFIG_KEY, useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
7
+
8
+ const editor = {
9
+ isActive: () => false,
10
+ can: () => ({ chain: () => ({ focus: () => ({ toggleBold: () => ({ run: () => false }) }) }) }),
11
+ commands: { toggleBold: () => {} },
12
+ }
13
+
14
+ const Consumer = {
15
+ setup () {
16
+ const { variantBtn, variantField } = useTiptapifyConfig()
17
+ return () => h('span', [
18
+ h('span', { id: 'variant-btn' }, variantBtn.value),
19
+ h('span', { id: 'variant-field' }, variantField.value),
20
+ ])
21
+ },
22
+ }
23
+
24
+ function render (root: () => any, withConfig: boolean) {
25
+ const app = createSSRApp({
26
+ setup () {
27
+ if (withConfig) {
28
+ provide(TIPTAPIFY_CONFIG_KEY, {
29
+ variantBtn: ref('tonal'),
30
+ variantField: ref('outlined'),
31
+ })
32
+ }
33
+ provide('tiptapifyEditor', ref(editor))
34
+ provide('tiptapifyI18n', { t: (key: string) => key })
35
+ return root
36
+ },
37
+ })
38
+ app.use(createVuetify())
39
+
40
+ return renderToString(app)
41
+ }
42
+
43
+ describe('useTiptapifyConfig', () => {
44
+ it('exposes provided config values', async () => {
45
+ const html = await render(() => h(Consumer), true)
46
+
47
+ expect(html).toContain('<span id="variant-btn">tonal</span>')
48
+ expect(html).toContain('<span id="variant-field">outlined</span>')
49
+ })
50
+
51
+ it('falls back to defaults when no provider is present', async () => {
52
+ const html = await render(() => h(Consumer), false)
53
+
54
+ expect(html).toContain('<span id="variant-btn">flat</span>')
55
+ expect(html).toContain('<span id="variant-field">solo</span>')
56
+ })
57
+
58
+ it('is consumed by toolbar extension buttons', async () => {
59
+ const custom = await render(() => h(BoldButton), true)
60
+ const fallback = await render(() => h(BoldButton), false)
61
+
62
+ expect(custom).toContain('tonal')
63
+ expect(fallback).toContain('flat')
64
+ expect(custom).not.toEqual(fallback)
65
+ })
66
+ })
@@ -0,0 +1,17 @@
1
+ import { computed, inject, InjectionKey, Ref } from 'vue'
2
+ import defaults from '@tiptapify/constants/defaults'
3
+ import { variantBtnTypes, variantFieldTypes } from '@tiptapify/types/editor'
4
+
5
+ export interface TiptapifyConfig {
6
+ variantBtn: Ref<variantBtnTypes>
7
+ variantField: Ref<variantFieldTypes>
8
+ }
9
+
10
+ export const TIPTAPIFY_CONFIG_KEY: InjectionKey<TiptapifyConfig> = Symbol('tiptapifyConfig')
11
+
12
+ export function useTiptapifyConfig(): TiptapifyConfig {
13
+ return inject(TIPTAPIFY_CONFIG_KEY, {
14
+ variantBtn: computed(() => defaults.variantBtn),
15
+ variantField: computed(() => defaults.variantField),
16
+ })
17
+ }
@@ -1,4 +1,6 @@
1
+ import { variantBtnTypes, variantFieldTypes } from '@tiptapify/types/editor'
2
+
1
3
  export default {
2
- variantBtn: 'flat',
3
- variantField: 'solo',
4
+ variantBtn: 'flat' as variantBtnTypes,
5
+ variantField: 'solo' as variantFieldTypes,
4
6
  }
@@ -3,15 +3,13 @@
3
3
  import * as mdi from '@mdi/js'
4
4
  import { Editor } from '@tiptap/vue-3'
5
5
  import BtnIcon from '@tiptapify/components/UI/BtnIcon.vue'
6
- import { variantBtnTypes } from '@tiptapify/types/editor'
7
- import { inject, PropType, Ref } from 'vue'
6
+ import Tooltip from '@tiptapify/components/UI/Tooltip.vue'
7
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
8
+ import { inject, Ref } from 'vue'
8
9
 
9
- import defaults from '@tiptapify/constants/defaults'
10
10
  import { ComposerTranslation } from 'vue-i18n'
11
11
 
12
- defineProps({
13
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
14
- })
12
+ const { variantBtn } = useTiptapifyConfig()
15
13
 
16
14
  const editor = inject('tiptapifyEditor') as Ref<Editor>
17
15
 
@@ -27,9 +25,7 @@ const { t } = inject('tiptapifyI18n') as { t: ComposerTranslation }
27
25
  :variant="variantBtn"
28
26
  @click="editor.chain().focus().redo().run()"
29
27
  >
30
- <VTooltip activator="parent">
31
- {{ t('action.redo') }}
32
- </VTooltip>
28
+ <Tooltip :label="t('action.redo')" hotkey="Mod-Shift-z" />
33
29
  <BtnIcon :icon="`mdiSvg:${mdi.mdiRedo}`" />
34
30
  </VBtn>
35
31
  </template>
@@ -3,15 +3,13 @@
3
3
  import * as mdi from '@mdi/js'
4
4
  import { Editor } from '@tiptap/vue-3'
5
5
  import BtnIcon from '@tiptapify/components/UI/BtnIcon.vue'
6
- import { variantBtnTypes } from '@tiptapify/types/editor'
7
- import { inject, PropType, Ref } from 'vue'
6
+ import Tooltip from '@tiptapify/components/UI/Tooltip.vue'
7
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
8
+ import { inject, Ref } from 'vue'
8
9
 
9
- import defaults from '@tiptapify/constants/defaults'
10
10
  import { ComposerTranslation } from 'vue-i18n'
11
11
 
12
- defineProps({
13
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
14
- })
12
+ const { variantBtn } = useTiptapifyConfig()
15
13
 
16
14
  const editor = inject('tiptapifyEditor') as Ref<Editor>
17
15
 
@@ -27,9 +25,7 @@ const { t } = inject('tiptapifyI18n') as { t: ComposerTranslation }
27
25
  :variant="variantBtn"
28
26
  @click="editor.chain().focus().undo().run()"
29
27
  >
30
- <VTooltip activator="parent">
31
- {{ t('action.undo') }}
32
- </VTooltip>
28
+ <Tooltip :label="t('action.undo')" hotkey="Mod-z" />
33
29
  <BtnIcon :icon="`mdiSvg:${mdi.mdiUndo}`" />
34
30
  </VBtn>
35
31
  </template>
@@ -2,15 +2,14 @@
2
2
 
3
3
  import * as mdi from '@mdi/js'
4
4
  import BtnIcon from '@tiptapify/components/UI/BtnIcon.vue'
5
+ import Tooltip from '@tiptapify/components/UI/Tooltip.vue'
5
6
  import AiDialog from '@tiptapify/extensions/components/ai/Dialog.vue'
6
- import defaults from '@tiptapify/constants/defaults'
7
- import { TiptapifyAiResolvedOptions, variantBtnTypes } from '@tiptapify/types/editor'
8
- import { computed, ComputedRef, inject, PropType, useTemplateRef } from 'vue'
7
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
8
+ import { TiptapifyAiResolvedOptions } from '@tiptapify/types/editor'
9
+ import { computed, ComputedRef, inject, useTemplateRef } from 'vue'
9
10
  import { ComposerTranslation } from 'vue-i18n'
10
11
 
11
- defineProps({
12
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
13
- })
12
+ const { variantBtn } = useTiptapifyConfig()
14
13
 
15
14
  const { t } = inject('tiptapifyI18n') as { t: ComposerTranslation }
16
15
  const ai = inject('tiptapifyAi') as ComputedRef<TiptapifyAiResolvedOptions | false>
@@ -32,11 +31,9 @@ function showDialog() {
32
31
 
33
32
  <template>
34
33
  <VBtn color="" :variant="variantBtn" size="32" :disabled="!isAvailable" @click="showDialog">
35
- <VTooltip activator="parent">
36
- {{ isAvailable ? t('ai.title') : t('ai.unavailable') }}
37
- </VTooltip>
34
+ <Tooltip :label="isAvailable ? t('ai.title') : t('ai.unavailable')" />
38
35
  <BtnIcon :icon="icon" />
39
36
  </VBtn>
40
37
 
41
- <AiDialog ref="dialog" :variant-btn="variantBtn" />
38
+ <AiDialog ref="dialog" />
42
39
  </template>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts" setup>
2
2
 
3
3
  import TiptapifyDialog from '@tiptapify/components/UI/TiptapifyDialog.vue'
4
- import defaults from '@tiptapify/constants/defaults'
4
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
5
5
  import {
6
6
  TiptapifyAiEditorContext,
7
7
  TiptapifyAiMode,
@@ -11,20 +11,15 @@ import {
11
11
  TiptapifyAiResponse,
12
12
  TiptapifyAiResolvedOptions,
13
13
  TiptapifyAiStream,
14
- TiptapifyEditor,
15
- variantBtnTypes,
16
- variantFieldTypes
14
+ TiptapifyEditor
17
15
  } from '@tiptapify/types/editor'
18
- import { computed, ComputedRef, inject, nextTick, PropType, Ref, ref, useTemplateRef, watch } from 'vue'
16
+ import { computed, ComputedRef, inject, nextTick, Ref, ref, useTemplateRef, watch } from 'vue'
19
17
  import * as mdi from '@mdi/js'
20
18
  import { ComposerTranslation } from 'vue-i18n'
21
19
  import { exceedsLimit } from './charLimit'
22
20
  import { DEFAULT_AI_INSTRUCTION } from './backend'
23
21
 
24
- defineProps({
25
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
26
- variantField: { type: String as PropType<variantFieldTypes>, default() { return defaults.variantField } },
27
- })
22
+ const { variantBtn, variantField } = useTiptapifyConfig()
28
23
 
29
24
  const editor = inject('tiptapifyEditor') as Ref<TiptapifyEditor>
30
25
  const ai = inject('tiptapifyAi') as ComputedRef<TiptapifyAiResolvedOptions | false>
@@ -3,15 +3,13 @@
3
3
  import * as mdi from '@mdi/js'
4
4
  import { Editor } from '@tiptap/vue-3'
5
5
  import BtnIcon from '@tiptapify/components/UI/BtnIcon.vue'
6
- import { variantBtnTypes } from '@tiptapify/types/editor'
7
- import { inject, PropType, Ref } from 'vue'
6
+ import Tooltip from '@tiptapify/components/UI/Tooltip.vue'
7
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
8
+ import { inject, Ref } from 'vue'
8
9
 
9
- import defaults from '@tiptapify/constants/defaults'
10
10
  import { ComposerTranslation } from 'vue-i18n'
11
11
 
12
- defineProps({
13
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
14
- })
12
+ const { variantBtn } = useTiptapifyConfig()
15
13
 
16
14
  const editor = inject('tiptapifyEditor') as Ref<Editor>
17
15
 
@@ -26,9 +24,7 @@ const { t } = inject('tiptapifyI18n') as { t: ComposerTranslation }
26
24
  size="32"
27
25
  @click="editor.chain().focus().toggleTextAlign('center').run()"
28
26
  >
29
- <VTooltip activator="parent">
30
- {{ t('alignments.center') }}
31
- </VTooltip>
27
+ <Tooltip :label="t('alignments.center')" hotkey="Mod-Shift-e" />
32
28
  <BtnIcon :icon="`mdiSvg:${mdi.mdiFormatAlignCenter}`" />
33
29
  </VBtn>
34
30
  </template>
@@ -3,15 +3,13 @@
3
3
  import * as mdi from '@mdi/js'
4
4
  import { Editor } from '@tiptap/vue-3'
5
5
  import BtnIcon from '@tiptapify/components/UI/BtnIcon.vue'
6
- import { variantBtnTypes } from '@tiptapify/types/editor'
7
- import { inject, PropType, Ref } from 'vue'
6
+ import Tooltip from '@tiptapify/components/UI/Tooltip.vue'
7
+ import { useTiptapifyConfig } from '@tiptapify/composables/useTiptapifyConfig'
8
+ import { inject, Ref } from 'vue'
8
9
 
9
- import defaults from '@tiptapify/constants/defaults'
10
10
  import { ComposerTranslation } from 'vue-i18n'
11
11
 
12
- defineProps({
13
- variantBtn: { type: String as PropType<variantBtnTypes>, default() { return defaults.variantBtn } },
14
- })
12
+ const { variantBtn } = useTiptapifyConfig()
15
13
 
16
14
  const editor = inject('tiptapifyEditor') as Ref<Editor>
17
15
 
@@ -26,9 +24,7 @@ const { t } = inject('tiptapifyI18n') as { t: ComposerTranslation }
26
24
  size="32"
27
25
  @click="editor.chain().focus().toggleTextAlign('justify').run()"
28
26
  >
29
- <VTooltip activator="parent">
30
- {{ t('alignments.justify') }}
31
- </VTooltip>
27
+ <Tooltip :label="t('alignments.justify')" hotkey="Mod-Shift-j" />
32
28
  <BtnIcon :icon="`mdiSvg:${mdi.mdiFormatAlignJustify}`" />
33
29
  </VBtn>
34
30
  </template>