tiptapify 0.0.4 → 0.0.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 (36) hide show
  1. package/README.md +9 -1
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/tiptapify.es.js +20861 -19932
  4. package/dist/tiptapify.umd.js +39 -32
  5. package/package.json +23 -10
  6. package/src/components/MenuBubble.vue +25 -20
  7. package/src/components/MenuFloating.vue +35 -31
  8. package/src/components/Tiptapify.vue +51 -14
  9. package/src/components/Toolbar/Group.vue +78 -0
  10. package/src/components/Toolbar/Index.vue +44 -71
  11. package/src/components/Toolbar/Toggle.vue +33 -0
  12. package/src/components/Toolbar/fonts.ts +118 -0
  13. package/src/components/Toolbar/items/actions.ts +32 -0
  14. package/src/components/Toolbar/items/alignment.ts +60 -0
  15. package/src/components/Toolbar/items/format.ts +73 -0
  16. package/src/components/Toolbar/items/formatExtra.ts +73 -0
  17. package/src/components/Toolbar/items/list.ts +70 -0
  18. package/src/components/Toolbar/items/media.ts +25 -0
  19. package/src/components/Toolbar/items/misc.ts +50 -0
  20. package/src/components/Toolbar/items/style.ts +146 -0
  21. package/src/components/Toolbar/items.ts +72 -635
  22. package/src/components/editorExtensions.ts +3 -1
  23. package/src/components/extensions/components/LinkDialog.vue +1 -1
  24. package/src/components/extensions/components/ShowSource.vue +124 -0
  25. package/src/components/extensions/view-source.ts +53 -0
  26. package/src/i18n/locales/de.json +67 -0
  27. package/src/i18n/locales/en.json +11 -2
  28. package/src/i18n/locales/es.json +67 -0
  29. package/src/i18n/locales/fr.json +67 -0
  30. package/src/i18n/locales/it.json +67 -0
  31. package/src/i18n/locales/pl.json +67 -0
  32. package/src/i18n/locales/ru.json +11 -2
  33. package/src/i18n/locales/ua.json +11 -2
  34. package/components.d.ts +0 -20
  35. package/tsconfig.json +0 -22
  36. package/vite.config.ts +0 -86
package/package.json CHANGED
@@ -1,16 +1,29 @@
1
1
  {
2
2
  "name": "tiptapify",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Tiptap3 editor with Vuetify3 menu implementation",
5
5
  "exports": {
6
6
  ".": {
7
- "import": "./dist/tiptapify.es.js",
8
- "require": "./dist/tiptapify.umd.js"
7
+ "import": {
8
+ "default": "./dist/tiptapify.es.js",
9
+ "development": "./src/index.ts"
10
+ },
11
+ "require": {
12
+ "default": "./dist/tiptapify.umd.js",
13
+ "development": "./src/index.ts"
14
+ }
9
15
  },
16
+ "./src/*": "./src/*",
17
+ "./dist/*": "./dist/*",
10
18
  "./style.css": "./dist/tiptapify.css"
11
19
  },
12
20
  "main": "./dist/tiptapify.umd.cjs",
13
21
  "module": "./dist/tiptapify.js",
22
+ "source": "./src/index.ts",
23
+ "files": [
24
+ "dist",
25
+ "src"
26
+ ],
14
27
  "scripts": {
15
28
  "dev": "vite",
16
29
  "build": "vite build",
@@ -38,7 +51,6 @@
38
51
  "repository": "https://github.com/IVoyt/tiptapify",
39
52
  "packageManager": "pnpm@10.11.0",
40
53
  "dependencies": {
41
- "@intlify/unplugin-vue-i18n": "^6.0.8",
42
54
  "@tiptap/core": "next",
43
55
  "@tiptap/extension-blockquote": "next",
44
56
  "@tiptap/extension-bold": "next",
@@ -77,15 +89,9 @@
77
89
  "@tiptap/starter-kit": "next",
78
90
  "@tiptap/suggestion": "next",
79
91
  "@tiptap/vue-3": "next",
80
- "@vitejs/plugin-vue": "^5.2.4",
81
- "@vitejs/plugin-vue-jsx": "^4.2.0",
82
92
  "highlight.js": "^11.11.1",
83
93
  "linkifyjs": "^4.3.1",
84
94
  "lowlight": "^3.3.0",
85
- "unplugin-vue-components": "^28.5.0",
86
- "vite": "^6.3.5",
87
- "vite-plugin-vuetify": "^2.1.1",
88
- "vite-svg-loader": "^5.1.0",
89
95
  "vue-i18n": "^11.1.4"
90
96
  },
91
97
  "peerDependencies": {
@@ -94,11 +100,18 @@
94
100
  "vuetify": "^3.8.5"
95
101
  },
96
102
  "devDependencies": {
103
+ "@intlify/unplugin-vue-i18n": "^6.0.8",
97
104
  "@rollup/plugin-alias": "^5.1.1",
98
105
  "@types/node": "^22.15.21",
106
+ "@vitejs/plugin-vue": "^5.2.4",
107
+ "@vitejs/plugin-vue-jsx": "^4.2.0",
99
108
  "rollup-plugin-tsconfig-paths": "^1.5.2",
100
109
  "sass-embedded": "^1.89.0",
101
110
  "typescript": "^5.8.3",
111
+ "unplugin-vue-components": "^28.5.0",
112
+ "vite": "^6.3.5",
113
+ "vite-plugin-vuetify": "^2.1.1",
114
+ "vite-svg-loader": "^5.1.0",
102
115
  "vite-tsconfig-paths": "^5.1.4",
103
116
  "vue-tsc": "^2.2.10"
104
117
  }
@@ -7,6 +7,7 @@ import * as mdi from '@mdi/js'
7
7
 
8
8
  defineProps({
9
9
  variant: { type: String, default () { return 'flat' }},
10
+ theme: { type: String, default () { return 'light' }},
10
11
  })
11
12
 
12
13
  const { editor } = useEditor()
@@ -19,7 +20,6 @@ const items = ref([
19
20
  name: 'bold',
20
21
  icon: mdi.mdiFormatBold,
21
22
  props: {
22
- active: false,
23
23
  disabled: computed(() => !editorInstance.value.can().chain().focus().toggleBold().run()),
24
24
  color: computed(() => editorInstance.value.isActive('bold') ? 'primary' : ''),
25
25
  },
@@ -29,7 +29,6 @@ const items = ref([
29
29
  name: 'italic',
30
30
  icon: mdi.mdiFormatItalic,
31
31
  props: {
32
- active: false,
33
32
  disabled: computed(() => !editorInstance.value.can().chain().focus().toggleItalic().run()),
34
33
  color: computed(() => editorInstance.value.isActive('italic') ? 'primary' : ''),
35
34
  },
@@ -39,7 +38,6 @@ const items = ref([
39
38
  name: 'strike',
40
39
  icon: mdi.mdiFormatStrikethroughVariant,
41
40
  props: {
42
- active: false,
43
41
  disabled: computed(() => !editorInstance.value.can().chain().focus().toggleStrike().run()),
44
42
  color: computed(() => editorInstance.value.isActive('strike') ? 'primary' : ''),
45
43
  },
@@ -49,7 +47,6 @@ const items = ref([
49
47
  name: 'underline',
50
48
  icon: mdi.mdiFormatUnderline,
51
49
  props: {
52
- active: false,
53
50
  disabled: computed(() => !editorInstance.value.can().chain().focus().toggleUnderline().run()),
54
51
  color: computed(() => editorInstance.value.isActive('underline') ? 'primary' : ''),
55
52
  },
@@ -59,17 +56,24 @@ const items = ref([
59
56
  name: 'highlight',
60
57
  icon: mdi.mdiFormatColorHighlight,
61
58
  props: {
62
- active: false,
63
59
  disabled: computed(() => !editorInstance.value.can().chain().focus().toggleHighlight().run()),
64
60
  color: computed(() => editorInstance.value.isActive('highlight') ? 'primary' : ''),
65
61
  },
66
62
  click: () => editorInstance.value.chain().focus().toggleHighlight().run(),
67
63
  },
64
+ {
65
+ name: 'code',
66
+ icon: mdi.mdiXml,
67
+ props: {
68
+ disabled: computed(() => !editorInstance.value.can().chain().focus().toggleCode().run()),
69
+ color: computed(() => editorInstance.value.isActive('code') ? 'primary' : ''),
70
+ },
71
+ click: () => editorInstance.value.chain().focus().toggleCode().run(),
72
+ },
68
73
  {
69
74
  name: 'link',
70
75
  icon: computed(() => editorInstance.value.isActive('link') ? mdi.mdiLinkOff : mdi.mdiLink),
71
76
  props: {
72
- active: false,
73
77
  color: computed(() => editorInstance.value.isActive('link') ? 'primary' : ''),
74
78
  disabled: computed(() => editorInstance.value.isActive('code') || editorInstance.value.isActive('codeBlock')),
75
79
  },
@@ -78,9 +82,6 @@ const items = ref([
78
82
  {
79
83
  name: 'format clear',
80
84
  icon: mdi.mdiFormatClear,
81
- props: {
82
- active: false,
83
- },
84
85
  click: () => editorInstance.value.chain().focus().unsetAllMarks().clearNodes().run(),
85
86
  }
86
87
  ])
@@ -93,14 +94,21 @@ function linkAction() {
93
94
  </script>
94
95
 
95
96
  <template>
96
- <!-- <BubbleMenu v-if="editorInstance" :editor="editorInstance" :tippy-options="{ duration: 100 }">-->
97
97
  <BubbleMenu v-if="editorInstance" :editor="editorInstance" :options="{ placement: 'bottom' }">
98
98
  <div class="bubble-menu">
99
- <VBtnToggle divided density="compact" :variant="variant">
100
- <VBtn v-for="(item, key) in items" :key="key" v-bind="item.props" @click="item.click" size="small">
101
- <VIcon :icon="item.icon" size="16" />
102
- </VBtn>
103
- </VBtnToggle>
99
+ <VCard>
100
+ <VCardText class="pa-0">
101
+ <VToolbar :theme="theme" density="compact" height="auto" class="p-0">
102
+ <VToolbarItems>
103
+ <VBtnGroup divided density="compact">
104
+ <VBtn v-for="(item, key) in items" :key="key" v-bind="item.props" @click="item.click" size="x-small">
105
+ <VIcon :icon="item.icon" size="20" />
106
+ </VBtn>
107
+ </VBtnGroup>
108
+ </VToolbarItems>
109
+ </VToolbar>
110
+ </VCardText>
111
+ </VCard>
104
112
  </div>
105
113
  </BubbleMenu>
106
114
 
@@ -109,10 +117,7 @@ function linkAction() {
109
117
 
110
118
  <style scoped lang="scss">
111
119
  .bubble-menu {
112
- border-radius: 4px;
113
- border-color: var(--gray-3);
114
- border-style: solid;
115
- border-width: 1px;
116
- box-shadow: var(--shadow);
120
+ border-radius: 6px;
121
+ box-shadow: 4px 4px 20px var(--dark-gray);
117
122
  }
118
123
  </style>
@@ -6,49 +6,53 @@ import * as mdi from '@mdi/js'
6
6
 
7
7
  defineProps({
8
8
  variant: { type: String, default () { return '' }},
9
+ theme: { type: String, default () { return 'light' }},
9
10
  })
10
11
 
11
- const { editor } = useEditor()
12
- const editorInstance = ref(editor.getInstance())
12
+ const editorInstance = ref(useEditor().editor.getInstance())
13
13
  </script>
14
14
 
15
15
  <template>
16
- <!-- <FloatingMenu v-if="editorInstance" :editor="editorInstance" :tippy-options="{ duration: 100 }" >-->
17
16
  <FloatingMenu v-if="editorInstance" :editor="editorInstance">
18
17
  <div class="floating-menu">
19
- <VBtnToggle divided density="compact" :variant="`${variant || 'plain'}`">
20
- <VBtn
21
- @click="editorInstance.chain().focus().toggleHeading({ level: 1 }).run()"
22
- :color="`${editorInstance.isActive('heading', { level: 1 }) ? 'primary' : ''}`"
23
- size="small"
24
- >
25
- <VIcon :icon="mdi['mdiFormatHeader1']" size="16" />
26
- </VBtn>
27
- <VBtn
28
- @click="editorInstance.chain().focus().toggleHeading({ level: 2 }).run()"
29
- :color="`${editorInstance.isActive('heading', { level: 2 }) ? 'primary' : ''}`"
30
- size="small"
31
- >
32
- <VIcon :icon="mdi['mdiFormatHeader2']" size="16" />
33
- </VBtn>
34
- <VBtn
35
- @click="editorInstance.chain().focus().toggleBulletList().run()"
36
- :color="`${editorInstance.isActive('bulletList') ? 'primary' : ''}`"
37
- size="small"
38
- >
39
- <VIcon :icon="mdi['mdiFormatListBulleted']" size="16" />
40
- </VBtn>
41
- </VBtnToggle>
18
+ <VCard>
19
+ <VCardText class="pa-0">
20
+ <VToolbar :theme="theme" density="compact" height="auto" class="p-0">
21
+ <VToolbarItems>
22
+ <VBtnGroup divided density="compact">
23
+ <VBtn
24
+ @click="editorInstance.chain().focus().toggleHeading({ level: 1 }).run()"
25
+ :color="`${editorInstance.isActive('heading', { level: 1 }) ? 'primary' : ''}`"
26
+ size="small"
27
+ >
28
+ <VIcon :icon="mdi['mdiFormatHeader1']" size="16" />
29
+ </VBtn>
30
+ <VBtn
31
+ @click="editorInstance.chain().focus().toggleHeading({ level: 2 }).run()"
32
+ :color="`${editorInstance.isActive('heading', { level: 2 }) ? 'primary' : ''}`"
33
+ size="small"
34
+ >
35
+ <VIcon :icon="mdi['mdiFormatHeader2']" size="16" />
36
+ </VBtn>
37
+ <VBtn
38
+ @click="editorInstance.chain().focus().toggleBulletList().run()"
39
+ :color="`${editorInstance.isActive('bulletList') ? 'primary' : ''}`"
40
+ size="small"
41
+ >
42
+ <VIcon :icon="mdi['mdiFormatListBulleted']" size="16" />
43
+ </VBtn>
44
+ </VBtnGroup>
45
+ </VToolbarItems>
46
+ </VToolbar>
47
+ </VCardText>
48
+ </VCard>
42
49
  </div>
43
50
  </FloatingMenu>
44
51
  </template>
45
52
 
46
53
  <style scoped lang="scss">
47
54
  .floating-menu {
48
- border-radius: 4px;
49
- border-color: var(--gray-3);
50
- border-style: solid;
51
- border-width: 1px;
52
- box-shadow: var(--shadow);
55
+ border-radius: 6px;
56
+ box-shadow: 4px 4px 20px var(--dark-gray);
53
57
  }
54
58
  </style>
@@ -8,10 +8,11 @@ import MenuBubble from '@tiptapify/components/MenuBubble.vue'
8
8
  import MenuFloating from '@tiptapify/components/MenuFloating.vue'
9
9
 
10
10
  import Footer from '@tiptapify/components/Footer.vue'
11
+ import { useTheme } from "vuetify/framework";
11
12
 
12
13
  const props = defineProps({
13
14
  content: String|Object,
14
- variant: { type: String, default () { return 'flat' } },
15
+ variant: { type: String, default () { return 'elevated' } },
15
16
  toolbar: { type: Boolean, default () { return true } },
16
17
  items: { type: Array<string>, default() { return [] }},
17
18
  itemsExclude: { type: Boolean, default() { return false } },
@@ -22,8 +23,11 @@ const props = defineProps({
22
23
  showCharacterCount: { type: Boolean, default () { return true } },
23
24
  defaultFontFamily: { type: String, default () { return 'Inter' } },
24
25
  fontMeasure: { type: String, default () { return 'px' } },
26
+ rounded: { type: String, default () { return '0' } },
25
27
  })
26
28
 
29
+ const theme = ref(useTheme().current.value.dark ? 'dark' : 'light')
30
+
27
31
  const editor = useEditor(props.content, props.placeholder, props.slashCommands).editor
28
32
  const editorInstance = ref(editor.getInstance())
29
33
  editorInstance?.value?.chain().setFontFamily(props.defaultFontFamily).run()
@@ -38,21 +42,22 @@ onBeforeUnmount(() => {
38
42
  <VContainer>
39
43
  <VRow>
40
44
  <VCol>
41
- <div class="border rounded">
42
- <template v-if="toolbar">
43
- <Toolbar
44
- v-if="editorInstance"
45
- :variant="variant"
46
- :font-measure="fontMeasure"
47
- :items="items"
48
- :items-exclude="itemsExclude"
49
- />
50
- </template>
51
-
45
+ <template v-if="toolbar">
46
+ <Toolbar
47
+ v-if="editorInstance"
48
+ :variant="variant"
49
+ :font-measure="fontMeasure"
50
+ :items="items"
51
+ :items-exclude="itemsExclude"
52
+ :rounded="rounded"
53
+ />
54
+ </template>
55
+
56
+ <div :class="`border border-t-0 rounded-b-${rounded}`">
52
57
  <div class="pa-2 tiptapify-container">
53
- <MenuFloating v-if="floatingMenu" />
58
+ <MenuFloating v-if="floatingMenu" :variant="variant" :theme="theme" />
54
59
 
55
- <MenuBubble v-if="bubbleMenu" />
60
+ <MenuBubble v-if="bubbleMenu" :variant="variant" :theme="theme" />
56
61
 
57
62
  <EditorContent :editor="editorInstance" class="tiptapify-editor" />
58
63
  </div>
@@ -77,6 +82,8 @@ onBeforeUnmount(() => {
77
82
  --white: #FFF;
78
83
  --black: #2E2B29;
79
84
  --black-contrast: #110F0E;
85
+ --dark-gray: rgb(98, 98, 98);
86
+ --gray: rgb(223 223 223);
80
87
  --gray-1: rgba(61, 37, 20, .05);
81
88
  --gray-2: rgba(61, 37, 20, .08);
82
89
  --gray-3: rgba(61, 37, 20, .12);
@@ -135,6 +142,36 @@ onBeforeUnmount(() => {
135
142
  }
136
143
  }
137
144
 
145
+ /* Task list specific styles */
146
+ ul[data-type='taskList'] {
147
+ list-style: none;
148
+ margin-left: 0;
149
+ padding: 0;
150
+
151
+ li {
152
+ align-items: flex-start;
153
+ display: flex;
154
+
155
+ > label {
156
+ flex: 0 0 auto;
157
+ margin-right: 0.5rem;
158
+ user-select: none;
159
+ }
160
+
161
+ > div {
162
+ flex: 1 1 auto;
163
+ }
164
+ }
165
+
166
+ input[type='checkbox'] {
167
+ cursor: pointer;
168
+ }
169
+
170
+ ul[data-type='taskList'] {
171
+ margin: 0;
172
+ }
173
+ }
174
+
138
175
  /* Heading styles */
139
176
  h1,
140
177
  h2,
@@ -0,0 +1,78 @@
1
+ <script setup lang="ts">
2
+ import { defineProps, PropType } from 'vue'
3
+ import { useI18n } from "vue-i18n";
4
+
5
+ import { ToolbarItemSection } from "@tiptapify/components/Toolbar/items";
6
+
7
+ defineProps({
8
+ variant: { type: String, default () { return 'flat' }},
9
+ section: { type: String, default() { return '' }},
10
+ toolbarSection: { type: Object as PropType<ToolbarItemSection>, default() { return {} }}
11
+ })
12
+
13
+ const { t } = useI18n();
14
+
15
+ </script>
16
+
17
+ <template>
18
+ <VBtnGroup :variant="variant" elevation="4">
19
+ <template v-for="(toolbarItem, toolbarItemKey) in toolbarSection.items" :key="toolbarItemKey">
20
+ <template v-if="toolbarItem.children">
21
+ <VMenu>
22
+ <template #activator="{ props: menuProps }">
23
+ <VBtn v-bind="{ ...menuProps, ...toolbarItem.props }" size="32">
24
+ <VTooltip :text="t(toolbarItem.tooltip)" location="top" activator="parent" />
25
+
26
+ <VIcon v-if="toolbarItem.icon" :icon="toolbarItem.icon" size="small" />
27
+ <span v-else class="menu-item-title">
28
+ {{ t(toolbarItem.name) }}
29
+ </span>
30
+ </VBtn>
31
+ </template>
32
+
33
+ <VList v-model="toolbarItem.modelValue" max-height="430px">
34
+ <VListItem
35
+ v-for="(item, menuItemKey) in toolbarItem.children"
36
+ :key="menuItemKey"
37
+ :value="item.name"
38
+ density="compact"
39
+ class="pa-0"
40
+ >
41
+ <VBtn
42
+ variant="flat"
43
+ rounded="0"
44
+ v-bind="item.props"
45
+ v-on="item.attrs"
46
+ >
47
+ <VTooltip v-if="item.tooltip" :text="t(item.tooltip)" location="top" activator="parent" />
48
+
49
+ <VIcon v-if="item.icon" :icon="item.icon" size="small" />
50
+ <span v-else class="menu-item-title">
51
+ <template v-if="item.noI18n">
52
+ {{ item.name }}
53
+ </template>
54
+ <template v-else>
55
+ {{ t(item.toggle) }}
56
+ </template>
57
+ </span>
58
+ </VBtn>
59
+ </VListItem>
60
+ </VList>
61
+ </VMenu>
62
+ </template>
63
+
64
+ <VBtn v-else v-bind="toolbarItem.props" v-on="toolbarItem.attrs" size="32">
65
+ <VTooltip :text="t(toolbarItem.tooltip)" location="top" activator="parent" />
66
+
67
+ <VIcon v-if="toolbarItem.icon" :icon="toolbarItem.icon" size="small" />
68
+ <span v-else class="menu-item-title">
69
+ {{ t(toolbarItem.name) }}
70
+ </span>
71
+ </VBtn>
72
+ </template>
73
+ </VBtnGroup>
74
+ </template>
75
+
76
+ <style lang="scss" scoped>
77
+
78
+ </style>
@@ -1,5 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import LinkDialog from "@tiptapify/components/extensions/components/LinkDialog.vue";
3
+ import ShowSource from "@tiptapify/components/extensions/components/ShowSource.vue";
4
+ import Group from "@tiptapify/components/Toolbar/Group.vue";
5
+ import Toggle from "@tiptapify/components/Toolbar/Toggle.vue";
3
6
  import { useEditor } from "@tiptapify/composable/useEditor";
4
7
  import { computed, defineProps, Ref, ref } from 'vue'
5
8
  import { useI18n } from "vue-i18n";
@@ -14,6 +17,8 @@ const props = defineProps({
14
17
  fontMeasure: { type: String, default () { return 'px' }},
15
18
  customFonts: { type: Array<string>, default () { return [] } },
16
19
  customFontsOverride: { type: Boolean, default() { return false } },
20
+ theme: { type: String, default() { return 'light' } },
21
+ rounded: { type: String, default() { return '0' } },
17
22
  })
18
23
 
19
24
  const { t } = useI18n();
@@ -35,82 +40,41 @@ const toolbarItemsRef: Ref<ToolbarItemSections> = ref(items)
35
40
  </script>
36
41
 
37
42
  <template>
38
- <div v-if="editor" class="d-flex flex-wrap gap-x-4 gap-y-2 tiptapify-menu">
39
- <template v-for="(toolbarItems, sectionKey) in toolbarItemsRef" :key="sectionKey">
40
- <template v-for="(toolbarItem, toolbarItemKey) in toolbarItems" :key="toolbarItemKey">
41
- <VDivider v-if="toolbarItem.name === '|'" vertical class="menu-divider" />
42
-
43
- <template v-else-if="toolbarItem.enabled">
44
- <template v-if="toolbarItem.children">
45
- <VBtnToggle v-if="toolbarItem.group" :variant="variant">
46
- <VBtn
47
- v-for="(item, key) of toolbarItem.children"
48
- v-bind="{ ...props, ...item.props}" v-on="item.attrs" size="32"
49
- :key="`${item.name}-${key}`"
50
- >
51
- <VTooltip :text="t(item.name)" location="top" activator="parent" />
52
-
53
- <VIcon v-if="item.icon" :icon="item.icon" size="small" />
54
- <span v-else class="menu-item-title">
55
- {{ t(toolbarItem.name) }}
56
- </span>
57
- </VBtn>
58
- </VBtnToggle>
59
-
60
- <VMenu v-else>
61
- <template #activator="{ props: menuProps }">
62
- <VBtn :variant="variant" v-bind="menuProps" size="32" class="menu-button">
63
- <VTooltip :text="t(toolbarItem.tooltip)" location="top" activator="parent" />
64
-
65
- <VIcon v-if="toolbarItem.icon" :icon="toolbarItem.icon" size="small" />
66
- <span v-else class="menu-item-title">
67
- {{ t(toolbarItem.name) }}
68
- </span>
69
- </VBtn>
70
- </template>
71
-
72
- <VList v-model="toolbarItem.modelValue" max-height="430px">
73
- <VListItem
74
- v-for="(item, menuItemKey) in toolbarItem.children"
75
- :key="menuItemKey"
76
- :value="item.name"
77
- density="compact"
78
- v-bind="item.props"
79
- v-on="item.attrs"
80
- >
81
- <VTooltip v-if="item.tooltip" :text="t(item.tooltip)" location="top" activator="parent" />
82
-
83
- <VListItemTitle>
84
- <VIcon v-if="item.icon" :icon="item.icon" size="small" />
85
- <span v-else class="menu-item-title">
86
- <template v-if="item.noI18n">
87
- {{ item.name }}
88
- </template>
89
- <template v-else>
90
- {{ t(item.name) }}
91
- </template>
92
- </span>
93
- </VListItemTitle>
94
- </VListItem>
95
- </VList>
96
- </VMenu>
97
- </template>
98
-
99
- <VBtn v-else :variant="variant" v-bind="toolbarItem.props" v-on="toolbarItem.attrs" class="menu-button" size="32">
43
+ <div v-if="editor">
44
+ <VToolbar elevation="1" :theme="theme" height="auto" :class="`ps-1 rounded-t-${rounded}`">
45
+ <VToolbarItems class="py-2">
46
+ <template v-for="(toolbarSection, sectionKey) in toolbarItemsRef" :key="sectionKey">
47
+ <Group v-if="toolbarSection.group" :variant="variant" :toolbar-section="toolbarSection" />
48
+
49
+ <Toggle v-else-if="toolbarSection.toggle" :variant="variant" :toolbar-section="toolbarSection" />
50
+
51
+ <VBtn
52
+ v-else
53
+ v-for="(toolbarItem, itemKey) in toolbarSection.items"
54
+ :key="itemKey"
55
+ :variant="variant"
56
+ v-bind="toolbarItem.props"
57
+ v-on="toolbarItem.attrs"
58
+ class="menu-button"
59
+ size="32"
60
+ elevation="4"
61
+ rounded="sm"
62
+ >
100
63
  <VTooltip :text="t(toolbarItem.tooltip)" location="top" activator="parent" />
101
64
 
102
65
  <VIcon v-if="toolbarItem.icon" :icon="toolbarItem.icon" size="16" />
103
66
  <span v-else class="menu-item-title">
104
- {{ t(toolbarItem.name) }}
105
- </span>
67
+ {{ t(toolbarItem.name) }}
68
+ </span>
106
69
  </VBtn>
107
- </template>
108
- </template>
109
70
 
110
- <VDivider vertical class="menu-divider" />
111
- </template>
71
+ <div class="menu-divider"></div>
72
+ </template>
73
+ </VToolbarItems>
74
+ </VToolbar>
112
75
 
113
76
  <LinkDialog ref="toolbarLinkButton" />
77
+ <ShowSource />
114
78
  </div>
115
79
  </template>
116
80
 
@@ -120,6 +84,10 @@ const toolbarItemsRef: Ref<ToolbarItemSections> = ref(items)
120
84
  border-bottom: var(--border);
121
85
  }
122
86
 
87
+ :deep(.toolbar__items) {
88
+ flex-wrap: wrap;
89
+ }
90
+
123
91
  :deep(.v-btn-group) {
124
92
  height: 32px !important;
125
93
  }
@@ -132,11 +100,16 @@ const toolbarItemsRef: Ref<ToolbarItemSections> = ref(items)
132
100
  margin: 0 1px;
133
101
  }
134
102
 
135
- .v-divider.menu-divider {
136
- margin: 0 10px;
103
+ .menu-divider {
104
+ margin: 0 4px;
137
105
  }
138
106
 
139
- .v-divider.menu-divider:nth-last-child(1) {
107
+ .menu-divider:nth-last-child(1) {
140
108
  display: none;
141
109
  }
110
+
111
+ .v-toolbar-items {
112
+ flex-wrap: wrap;
113
+ row-gap: 5px;
114
+ }
142
115
  </style>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ import { defineProps, PropType } from 'vue'
3
+ import { useI18n } from "vue-i18n";
4
+
5
+ import { ToolbarItemSection } from "@tiptapify/components/Toolbar/items";
6
+
7
+ defineProps({
8
+ variant: { type: String, default () { return 'flat' }},
9
+ toolbarSection: { type: Object as PropType<ToolbarItemSection>, default() { return {} }}
10
+ })
11
+
12
+ const { t } = useI18n();
13
+
14
+ </script>
15
+
16
+ <template>
17
+ <VBtnToggle :variant="variant" elevation="4">
18
+ <template v-for="(item, key) in toolbarSection.items" :key="key">
19
+ <VBtn v-bind="item.props" v-on="item.attrs" size="32">
20
+ <VTooltip :text="t(item.name)" location="top" activator="parent" />
21
+
22
+ <VIcon v-if="item.icon" :icon="item.icon" size="small" />
23
+ <span v-else class="menu-item-title">
24
+ {{ t(item.name) }}
25
+ </span>
26
+ </VBtn>
27
+ </template>
28
+ </VBtnToggle>
29
+ </template>
30
+
31
+ <style lang="scss" scoped>
32
+
33
+ </style>