tiptapify 0.0.35 → 0.1.0

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 (59) hide show
  1. package/README.md +12 -6
  2. package/package.json +7 -3
  3. package/src/components/Tiptapify.vue +95 -2
  4. package/src/components/Toolbar/Index.vue +10 -0
  5. package/src/components/Toolbar/Items.vue +17 -13
  6. package/src/components/Toolbar/media.ts +5 -0
  7. package/src/components/editorExtensions.ts +15 -6
  8. package/src/components/index.ts +2 -1
  9. package/src/extensions/PickerEventBus.ts +32 -0
  10. package/src/extensions/charmap/arrows.ts +1227 -0
  11. package/src/extensions/charmap/box_drawing.ts +324 -0
  12. package/src/extensions/charmap/currency.ts +157 -0
  13. package/src/extensions/charmap/cyrillic.ts +646 -0
  14. package/src/extensions/charmap/diacritics.ts +107 -0
  15. package/src/extensions/charmap/extended_letters.ts +1311 -0
  16. package/src/extensions/charmap/greek.ts +443 -0
  17. package/src/extensions/charmap/hebrew.ts +177 -0
  18. package/src/extensions/charmap/index.ts +75 -0
  19. package/src/extensions/charmap/math.ts +2949 -0
  20. package/src/extensions/charmap/punctuation.ts +121 -0
  21. package/src/extensions/charmap/symbols.ts +506 -0
  22. package/src/extensions/charmap/typography.ts +499 -0
  23. package/src/extensions/components/media/charmap/Button.vue +27 -0
  24. package/src/extensions/components/media/charmap/Picker.vue +229 -0
  25. package/src/extensions/components/media/emoji/Button.vue +6 -147
  26. package/src/extensions/components/media/emoji/Picker.vue +225 -0
  27. package/src/extensions/components/media/image/ImageDialog.vue +69 -27
  28. package/src/extensions/components/slashCommands/CommandsList.vue +65 -22
  29. package/src/extensions/components/slashCommands/PickerDialog.vue +44 -0
  30. package/src/extensions/components/slashCommands/suggestion.ts +152 -105
  31. package/src/extensions/slash-commands.ts +169 -9
  32. package/src/i18n/locales/ar.json +37 -14
  33. package/src/i18n/locales/ch.json +37 -14
  34. package/src/i18n/locales/cz.json +37 -14
  35. package/src/i18n/locales/de.json +37 -14
  36. package/src/i18n/locales/en.json +34 -12
  37. package/src/i18n/locales/es.json +37 -14
  38. package/src/i18n/locales/fi.json +37 -14
  39. package/src/i18n/locales/fr.json +37 -14
  40. package/src/i18n/locales/hu.json +37 -14
  41. package/src/i18n/locales/it.json +37 -14
  42. package/src/i18n/locales/ja.json +37 -14
  43. package/src/i18n/locales/ko.json +37 -14
  44. package/src/i18n/locales/la.json +37 -14
  45. package/src/i18n/locales/lt.json +37 -14
  46. package/src/i18n/locales/nl.json +37 -14
  47. package/src/i18n/locales/pl.json +37 -14
  48. package/src/i18n/locales/pt.json +37 -14
  49. package/src/i18n/locales/ru.json +37 -14
  50. package/src/i18n/locales/se.json +37 -14
  51. package/src/i18n/locales/th.json +37 -14
  52. package/src/i18n/locales/tr.json +37 -14
  53. package/src/i18n/locales/{ua.json → uk.json} +37 -14
  54. package/src/i18n/locales/vi.json +37 -14
  55. package/src/types/slashCommandsTypes.ts +19 -0
  56. package/src/types/toolbarTypes.ts +1 -1
  57. package/dist/tiptapify.css +0 -1
  58. package/dist/tiptapify.mjs +0 -82239
  59. package/dist/tiptapify.umd.js +0 -202
@@ -0,0 +1,229 @@
1
+ <script lang="ts" setup>
2
+ import type { Editor } from '@tiptap/core'
3
+ import tiptapifyCharMap from '@tiptapify/extensions/charmap'
4
+ import { PickerEventBus } from '@tiptapify/extensions/PickerEventBus'
5
+ import { computed, ref, watch } from 'vue'
6
+
7
+ const props = defineProps<{
8
+ editor: Editor,
9
+ t: any
10
+ }>()
11
+
12
+ const filter = ref('')
13
+ const activeTab = ref('punctuation')
14
+ const sorted = tiptapifyCharMap.sort((previous, current) => {
15
+ if (previous.order < current.order) {
16
+ return -1
17
+ }
18
+ if (previous.order > current.order) {
19
+ return 1
20
+ }
21
+ return 0
22
+ })
23
+
24
+ if (!activeTab.value && sorted.length > 0) {
25
+ activeTab.value = sorted[0].name
26
+ }
27
+
28
+ const chars = computed(() => sorted.map(item => ({ group: item.name, items: item.items })))
29
+ const filteredChars = ref(JSON.parse(JSON.stringify(chars.value)))
30
+
31
+ const handleCharacterClick = (charItem: any) => {
32
+ props.editor.chain().focus().insertContent(charItem.char).run()
33
+ PickerEventBus.emit('close', { type: 'charmap' })
34
+ }
35
+
36
+ const filterChars = () => {
37
+ if (!filter.value) {
38
+ filteredChars.value = JSON.parse(JSON.stringify(chars.value))
39
+ return
40
+ }
41
+
42
+ const filtered: any[] = []
43
+ filteredChars.value.forEach((group: any) => {
44
+ const matchingChars = group.items.filter((item: any) =>
45
+ item.name.toLowerCase().match(filter.value.toLowerCase())
46
+ )
47
+ if (matchingChars.length > 0) {
48
+ filtered.push({ ...group, items: matchingChars })
49
+ }
50
+ })
51
+ filteredChars.value = filtered
52
+ if (filtered.length > 0) {
53
+ activeTab.value = filtered[0].group
54
+ }
55
+ }
56
+
57
+ const resetFilter = () => {
58
+ filter.value = ''
59
+ filteredChars.value = JSON.parse(JSON.stringify(chars.value))
60
+ }
61
+
62
+ watch(filter, filterChars)
63
+ </script>
64
+
65
+ <template>
66
+ <div class="tiptapify-slash-picker">
67
+ <div class="tiptapify-slash-picker__sidebar">
68
+ <button
69
+ v-for="item in filteredChars"
70
+ :key="item.group"
71
+ :class="['tiptapify-slash-picker__tab', { 'tiptapify-slash-picker__tab--active': activeTab === item.group }]"
72
+ @click="activeTab = item.group"
73
+ >
74
+ <VTooltip activator="parent">
75
+ {{ t(`media.charmap.categories.${item.group}`) }}
76
+ </VTooltip>
77
+ {{ item.items[0]?.char }}
78
+ </button>
79
+ </div>
80
+
81
+ <div class="tiptapify-slash-picker__content">
82
+ <div class="tiptapify-slash-picker__search">
83
+ <input
84
+ v-model="filter"
85
+ type="text"
86
+ placeholder="Search characters..."
87
+ class="tiptapify-slash-picker__search-input"
88
+ />
89
+ <button v-if="filter" class="tiptapify-slash-picker__clear" @click="resetFilter">&times;</button>
90
+ </div>
91
+
92
+ <div class="tiptapify-slash-picker__grid-container">
93
+ <div
94
+ v-for="item in filteredChars"
95
+ :key="item.group"
96
+ class="tiptapify-slash-picker__group"
97
+ >
98
+ <div v-show="activeTab === item.group" class="tiptapify-slash-picker__grid">
99
+ <button
100
+ v-for="charItem in item.items"
101
+ :key="charItem.char"
102
+ class="tiptapify-slash-picker__item"
103
+ :title="charItem.name"
104
+ @click="handleCharacterClick(charItem)"
105
+ >
106
+ {{ charItem.char }}
107
+ </button>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </template>
114
+
115
+ <style scoped>
116
+ .tiptapify-slash-picker {
117
+ display: flex;
118
+ width: 450px;
119
+ height: 400px;
120
+ background: rgb(var(--v-theme-surface));
121
+ border-radius: 8px;
122
+ overflow: hidden;
123
+ }
124
+
125
+ .tiptapify-slash-picker__sidebar {
126
+ width: 48px;
127
+ background: rgba(var(--v-theme-on-surface), 0.04);
128
+ border-right: 1px solid rgba(var(--v-theme-on-surface), 0.12);
129
+ padding: 8px 4px;
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: 4px;
133
+ overflow-y: auto;
134
+ }
135
+
136
+ .tiptapify-slash-picker__tab {
137
+ width: 40px;
138
+ height: 32px;
139
+ font-size: 16px;
140
+ border: none;
141
+ background: transparent;
142
+ border-radius: 4px;
143
+ cursor: pointer;
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ }
148
+
149
+ .tiptapify-slash-picker__tab:hover {
150
+ background: rgba(var(--v-theme-on-surface), 0.08);
151
+ }
152
+
153
+ .tiptapify-slash-picker__tab--active {
154
+ background: rgba(var(--v-theme-primary), 0.12);
155
+ color: rgb(var(--v-theme-primary));
156
+ }
157
+
158
+ .tiptapify-slash-picker__content {
159
+ flex: 1;
160
+ display: flex;
161
+ flex-direction: column;
162
+ padding: 12px;
163
+ }
164
+
165
+ .tiptapify-slash-picker__search {
166
+ position: relative;
167
+ margin-bottom: 12px;
168
+ }
169
+
170
+ .tiptapify-slash-picker__search-input {
171
+ width: 100%;
172
+ padding: 8px 32px 8px 12px;
173
+ border: 1px solid rgba(var(--v-theme-on-surface), 0.24);
174
+ border-radius: 4px;
175
+ font-size: 14px;
176
+ background: rgb(var(--v-theme-surface));
177
+ color: rgb(var(--v-theme-on-surface));
178
+ }
179
+
180
+ .tiptapify-slash-picker__search-input:focus {
181
+ outline: none;
182
+ border-color: rgb(var(--v-theme-primary));
183
+ }
184
+
185
+ .tiptapify-slash-picker__clear {
186
+ position: absolute;
187
+ right: 8px;
188
+ top: 50%;
189
+ transform: translateY(-50%);
190
+ width: 20px;
191
+ height: 20px;
192
+ border: none;
193
+ background: transparent;
194
+ cursor: pointer;
195
+ font-size: 16px;
196
+ color: rgba(var(--v-theme-on-surface), 0.6);
197
+ }
198
+
199
+ .tiptapify-slash-picker__grid-container {
200
+ flex: 1;
201
+ overflow-y: auto;
202
+ border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
203
+ border-radius: 4px;
204
+ }
205
+
206
+ .tiptapify-slash-picker__grid {
207
+ display: grid;
208
+ grid-template-columns: repeat(auto-fill, minmax(32px, 1fr));
209
+ gap: 2px;
210
+ padding: 4px;
211
+ }
212
+
213
+ .tiptapify-slash-picker__item {
214
+ width: 32px;
215
+ height: 32px;
216
+ font-size: 16px;
217
+ border: none;
218
+ background: transparent;
219
+ border-radius: 4px;
220
+ cursor: pointer;
221
+ display: flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ }
225
+
226
+ .tiptapify-slash-picker__item:hover {
227
+ background: rgba(var(--v-theme-on-surface), 0.08);
228
+ }
229
+ </style>
@@ -1,78 +1,21 @@
1
1
  <script lang="ts" setup>
2
-
3
2
  import * as mdi from '@mdi/js'
4
- import { Editor } from "@tiptap/vue-3";
5
- import tiptapifyEmojis from "@tiptapify/extensions/emoji"
6
- import { computed, inject, Ref, ref, watch } from 'vue'
3
+ import { inject, Ref } from 'vue'
7
4
  import BtnIcon from "@tiptapify/components/UI/BtnIcon.vue";
8
-
5
+ import EmojiPicker from './Picker.vue';
9
6
  import defaults from '@tiptapify/constants/defaults'
10
7
 
11
8
  defineProps({
12
9
  variantBtn: { type: String, default: defaults.variantBtn }
13
10
  })
14
11
 
15
- const editor = inject('tiptapifyEditor') as Ref<Editor>
12
+ const editor = inject('tiptapifyEditor') as Ref<any>
16
13
 
17
14
  const { t } = inject('tiptapifyI18n') as any
18
-
19
- const filter = ref(null)
20
- const tab = ref('smileys_and_emotion')
21
- const sorted = tiptapifyEmojis.sort((previous, current) => {
22
- if (previous.order < current.order) {
23
- return -1
24
- }
25
- if (previous.order > current.order) {
26
- return 1
27
- }
28
-
29
- return 0
30
- })
31
- const emojis = computed(() => sorted.map(item => { return { group: item.name, emojis: item.items } }))
32
- const emojisRef = ref(JSON.parse(JSON.stringify(emojis.value)))
33
-
34
- const handleEmojiClick = (emoji: any) => {
35
- editor.value.chain().focus().insertContent(emoji.char).run()
36
- }
37
-
38
- const filterEmoji = (filterValue: string) => {
39
- resetFilter()
40
- if (!filterValue) {
41
- return
42
- }
43
-
44
- const filtered: any[] = []
45
-
46
- const groupItems = emojisRef.value.find((item: any) => item.group === tab.value)
47
- if (groupItems?.emojis) {
48
- groupItems.emojis.forEach((item: any) => {
49
- if (item.name.toLowerCase().match(filterValue)) {
50
- filtered.push(item)
51
- }
52
- })
53
-
54
- groupItems.emojis = filtered
55
- }
56
- }
57
-
58
- const resetFilter = () => {
59
- emojisRef.value = JSON.parse(JSON.stringify(emojis.value))
60
- }
61
-
62
- watch(() => tab.value, () => {
63
- resetFilter()
64
- filter.value = null
65
- })
66
-
67
15
  </script>
68
16
 
69
17
  <template>
70
- <VBtn
71
- :id="`tiptapify-emoji-button-${editor.instanceId}`"
72
- :color="editor.isActive('image') ? 'primary' : ''"
73
- :variant="variantBtn"
74
- size="32"
75
- >
18
+ <VBtn :id="`tiptapify-emoji-button-${editor.instanceId}`" color="" :variant="variantBtn" size="32">
76
19
  <VTooltip activator="parent">
77
20
  {{ t('media.emoji.title') }}
78
21
  </VTooltip>
@@ -81,91 +24,7 @@ watch(() => tab.value, () => {
81
24
 
82
25
  <VMenu :activator="`#tiptapify-emoji-button-${editor.instanceId}`" :close-on-content-click="false">
83
26
  <VSheet class="pa-2" max-width="570">
84
- <div class="d-flex flex-row">
85
- <VTabs v-model="tab" mandatory direction="vertical" color="primary" density="compact">
86
- <VTab
87
- v-for="item of emojisRef"
88
- :text="item.group"
89
- :value="item.group"
90
- :key="item.group"
91
- density="compact"
92
- rounded
93
- size="small"
94
- >
95
- {{ t(`media.emoji.${item.group}`) }}
96
- </VTab>
97
- </VTabs>
98
-
99
- <div>
100
- <VTextField
101
- v-model="filter"
102
- label="Filter emoji"
103
- density="compact"
104
- variant="solo"
105
- :prepend-inner-icon="`mdiSvg:${mdi.mdiMagnify}`"
106
- class="mb-2"
107
- hide-details
108
- clearable
109
- @input="filterEmoji($event.target.value)"
110
- @click:clear="resetFilter"
111
- />
112
- <div class="tiptapify-emoji-container">
113
- <VWindow v-model="tab" direction="vertical">
114
- <VWindowItem v-for="item of emojisRef" :value="item.group" :transition="false" :reverse-transition="false">
115
- <div
116
- v-for="emojiItem in item.emojis"
117
- class="tiptapify-emoji-container-item"
118
- @click="handleEmojiClick(emojiItem)"
119
- :title="emojiItem.name"
120
- >
121
- <div class="tiptapify-emoji-container-item__overlay">
122
- <span>
123
- {{ emojiItem.char }}
124
- </span>
125
- </div>
126
- </div>
127
- </VWindowItem>
128
- </VWindow>
129
- </div>
130
- </div>
131
- </div>
27
+ <EmojiPicker :editor="editor" :t="t" />
132
28
  </VSheet>
133
29
  </VMenu>
134
- </template>
135
-
136
- <style lang="scss" scoped>
137
- .tiptapify-emoji-container {
138
- width: 360px;
139
- height: 500px;
140
- overflow-y: auto;
141
-
142
- border: 1px solid rgba(var(--v-theme-on-background), calc(var(--v-border-opacity)));
143
- border-radius: 8px;
144
- box-shadow: 0 0 5px rgba(var(--v-theme-on-background), calc(var(--v-border-opacity))) inset;
145
- }
146
-
147
- .tiptapify-emoji-container-item__overlay {
148
- display: flex;
149
- justify-content: center;
150
- align-items: center;
151
- width: 32px;
152
- height: 32px;
153
- border-radius: 5px;
154
- z-index: 1;
155
- }
156
-
157
- .tiptapify-emoji-container-item {
158
- position: relative;
159
- display: inline-flex;
160
- justify-content: center;
161
- align-items: center;
162
- cursor: pointer;
163
- width: 32px;
164
- height: 32px;
165
- transition: background-color 0.2s ease-in-out;
166
- }
167
-
168
- .tiptapify-emoji-container-item:hover .tiptapify-emoji-container-item__overlay {
169
- background-color: rgba(var(--v-theme-on-background), calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier)));
170
- }
171
- </style>
30
+ </template>
@@ -0,0 +1,225 @@
1
+ <script lang="ts" setup>
2
+ import type { Editor } from '@tiptap/core'
3
+ import tiptapifyEmojis from '@tiptapify/extensions/emoji'
4
+ import { PickerEventBus } from '@tiptapify/extensions/PickerEventBus'
5
+ import { computed, ref, watch } from 'vue'
6
+
7
+ const props = defineProps<{
8
+ editor: Editor,
9
+ t: any
10
+ }>()
11
+
12
+ const filter = ref('')
13
+ const activeTab = ref('smileys_and_emotion')
14
+ const sorted = tiptapifyEmojis.sort((previous, current) => {
15
+ if (previous.order < current.order) {
16
+ return -1
17
+ }
18
+ if (previous.order > current.order) {
19
+ return 1
20
+ }
21
+ return 0
22
+ })
23
+
24
+ const emojis = computed(() => sorted.map(item => ({ group: item.name, emojis: item.items })))
25
+ const filteredEmojis = ref(JSON.parse(JSON.stringify(emojis.value)))
26
+
27
+ const handleEmojiClick = (emoji: any) => {
28
+ props.editor.chain().focus().insertContent(emoji.char).run()
29
+ PickerEventBus.emit('close', { type: 'emoji' })
30
+ }
31
+
32
+ const filterEmoji = () => {
33
+ if (!filter.value) {
34
+ filteredEmojis.value = JSON.parse(JSON.stringify(emojis.value))
35
+ return
36
+ }
37
+
38
+ const filtered: any[] = []
39
+ filteredEmojis.value.forEach((group: any) => {
40
+ const matchingEmojis = group.emojis.filter((emoji: any) =>
41
+ emoji.name.toLowerCase().match(filter.value.toLowerCase())
42
+ )
43
+ if (matchingEmojis.length > 0) {
44
+ filtered.push({ ...group, emojis: matchingEmojis })
45
+ }
46
+ })
47
+ filteredEmojis.value = filtered
48
+ if (filtered.length > 0) {
49
+ activeTab.value = filtered[0].group
50
+ }
51
+ }
52
+
53
+ const resetFilter = () => {
54
+ filter.value = ''
55
+ filteredEmojis.value = JSON.parse(JSON.stringify(emojis.value))
56
+ }
57
+
58
+ watch(filter, filterEmoji)
59
+ </script>
60
+
61
+ <template>
62
+ <div class="tiptapify-slash-picker">
63
+ <div class="tiptapify-slash-picker__sidebar">
64
+ <button
65
+ v-for="item in filteredEmojis"
66
+ :key="item.group"
67
+ :class="['tiptapify-slash-picker__tab', { 'tiptapify-slash-picker__tab--active': activeTab === item.group }]"
68
+ @click="activeTab = item.group"
69
+ >
70
+ <VTooltip activator="parent">
71
+ {{ t(`media.emoji.categories.${item.group}`) }}
72
+ </VTooltip>
73
+ {{ item.emojis[0]?.char }}
74
+ </button>
75
+ </div>
76
+
77
+ <div class="tiptapify-slash-picker__content">
78
+ <div class="tiptapify-slash-picker__search">
79
+ <input
80
+ v-model="filter"
81
+ type="text"
82
+ placeholder="Search emoji..."
83
+ class="tiptapify-slash-picker__search-input"
84
+ />
85
+ <button v-if="filter" class="tiptapify-slash-picker__clear" @click="resetFilter">&times;</button>
86
+ </div>
87
+
88
+ <div class="tiptapify-slash-picker__grid-container">
89
+ <div
90
+ v-for="item in filteredEmojis"
91
+ :key="item.group"
92
+ class="tiptapify-slash-picker__group"
93
+ >
94
+ <div v-show="activeTab === item.group" class="tiptapify-slash-picker__grid">
95
+ <button
96
+ v-for="emojiItem in item.emojis"
97
+ :key="emojiItem.char"
98
+ class="tiptapify-slash-picker__item"
99
+ :title="emojiItem.name"
100
+ @click="handleEmojiClick(emojiItem)"
101
+ >
102
+ {{ emojiItem.char }}
103
+ </button>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </template>
110
+
111
+ <style scoped>
112
+ .tiptapify-slash-picker {
113
+ display: flex;
114
+ width: 450px;
115
+ height: 400px;
116
+ background: rgb(var(--v-theme-surface));
117
+ border-radius: 8px;
118
+ overflow: hidden;
119
+ }
120
+
121
+ .tiptapify-slash-picker__sidebar {
122
+ width: 48px;
123
+ background: rgba(var(--v-theme-on-surface), 0.04);
124
+ border-right: 1px solid rgba(var(--v-theme-on-surface), 0.12);
125
+ padding: 8px 4px;
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 4px;
129
+ overflow-y: auto;
130
+ }
131
+
132
+ .tiptapify-slash-picker__tab {
133
+ width: 40px;
134
+ height: 32px;
135
+ font-size: 18px;
136
+ border: none;
137
+ background: transparent;
138
+ border-radius: 4px;
139
+ cursor: pointer;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ }
144
+
145
+ .tiptapify-slash-picker__tab:hover {
146
+ background: rgba(var(--v-theme-on-surface), 0.08);
147
+ }
148
+
149
+ .tiptapify-slash-picker__tab--active {
150
+ background: rgba(var(--v-theme-primary), 0.12);
151
+ color: rgb(var(--v-theme-primary));
152
+ }
153
+
154
+ .tiptapify-slash-picker__content {
155
+ flex: 1;
156
+ display: flex;
157
+ flex-direction: column;
158
+ padding: 12px;
159
+ }
160
+
161
+ .tiptapify-slash-picker__search {
162
+ position: relative;
163
+ margin-bottom: 12px;
164
+ }
165
+
166
+ .tiptapify-slash-picker__search-input {
167
+ width: 100%;
168
+ padding: 8px 32px 8px 12px;
169
+ border: 1px solid rgba(var(--v-theme-on-surface), 0.24);
170
+ border-radius: 4px;
171
+ font-size: 14px;
172
+ background: rgb(var(--v-theme-surface));
173
+ color: rgb(var(--v-theme-on-surface));
174
+ }
175
+
176
+ .tiptapify-slash-picker__search-input:focus {
177
+ outline: none;
178
+ border-color: rgb(var(--v-theme-primary));
179
+ }
180
+
181
+ .tiptapify-slash-picker__clear {
182
+ position: absolute;
183
+ right: 8px;
184
+ top: 50%;
185
+ transform: translateY(-50%);
186
+ width: 20px;
187
+ height: 20px;
188
+ border: none;
189
+ background: transparent;
190
+ cursor: pointer;
191
+ font-size: 16px;
192
+ color: rgba(var(--v-theme-on-surface), 0.6);
193
+ }
194
+
195
+ .tiptapify-slash-picker__grid-container {
196
+ flex: 1;
197
+ overflow-y: auto;
198
+ border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
199
+ border-radius: 4px;
200
+ }
201
+
202
+ .tiptapify-slash-picker__grid {
203
+ display: grid;
204
+ grid-template-columns: repeat(auto-fill, minmax(32px, 1fr));
205
+ gap: 2px;
206
+ padding: 4px;
207
+ }
208
+
209
+ .tiptapify-slash-picker__item {
210
+ width: 32px;
211
+ height: 32px;
212
+ font-size: 20px;
213
+ border: none;
214
+ background: transparent;
215
+ border-radius: 4px;
216
+ cursor: pointer;
217
+ display: flex;
218
+ align-items: center;
219
+ justify-content: center;
220
+ }
221
+
222
+ .tiptapify-slash-picker__item:hover {
223
+ background: rgba(var(--v-theme-on-surface), 0.08);
224
+ }
225
+ </style>