Skip to content

Commit a9c983a

Browse files
authored
feat(editor): markdown toolbar (#1008)
* feat: editor toolbar * fix: editor toolbar style * fix: toolbar action bugs
1 parent fb48c24 commit a9c983a

File tree

14 files changed

+973
-16
lines changed

14 files changed

+973
-16
lines changed

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/discord.xml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/mx-admin.iml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/prettier.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/editor/codemirror/codemirror.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
/* eslint-disable vue/no-setup-props-destructure */
2-
import { useSaveConfirm } from '~/hooks/use-save-confirm'
32
import { defineComponent } from 'vue'
43
import type { EditorState } from '@codemirror/state'
54
import type { PropType } from 'vue'
65

6+
import { useSaveConfirm } from '~/hooks/use-save-confirm'
7+
8+
import { MarkdownToolbar } from '../toolbar'
79
import styles from '../universal/editor.module.css'
810
import { editorBaseProps } from '../universal/props'
911

@@ -64,7 +66,13 @@ export const CodemirrorEditor = defineComponent({
6466
)
6567

6668
return () => (
67-
<div class={[styles.editor, props.className]} ref={refContainer} />
69+
<div class="flex h-full flex-col">
70+
<MarkdownToolbar editorView={editorView.value} />
71+
<div
72+
class={[styles.editor, props.className, 'flex-1']}
73+
ref={refContainer}
74+
/>
75+
</div>
6876
)
6977
},
7078
})

src/components/editor/codemirror/use-codemirror.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
lineNumbers,
2020
} from '@codemirror/view'
2121

22+
import { createToolbarKeymapExtension } from '../toolbar'
2223
import { useEditorConfig } from '../universal/use-editor-setting'
2324
import { codemirrorReconfigureExtension } from './extension'
2425
import { syntaxTheme } from './syntax-highlight'
@@ -80,7 +81,7 @@ export const useCodeMirror = <T extends Element>(
8081
})
8182
})
8283
.catch(() => {
83-
console.log('not support wasm')
84+
// not support wasm
8485
})
8586
}
8687
}
@@ -106,6 +107,7 @@ export const useCodeMirror = <T extends Element>(
106107
},
107108
},
108109
]),
110+
createToolbarKeymapExtension(),
109111
keymap.of([
110112
...defaultKeymap,
111113
...historyKeymap,
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
import { NScrollbar } from 'naive-ui'
2+
import { defineComponent } from 'vue'
3+
import type { PropType } from 'vue'
4+
5+
const EMOJI_GROUPS = {
6+
常用: [
7+
'😀',
8+
'😃',
9+
'😄',
10+
'😁',
11+
'😅',
12+
'😂',
13+
'🤣',
14+
'😊',
15+
'😇',
16+
'🙂',
17+
'😉',
18+
'😌',
19+
'😍',
20+
'🥰',
21+
'😘',
22+
'😗',
23+
'😙',
24+
'😚',
25+
'😋',
26+
'😛',
27+
'😝',
28+
'😜',
29+
'🤪',
30+
'🤨',
31+
'🧐',
32+
'🤓',
33+
],
34+
手势: [
35+
'👍',
36+
'👎',
37+
'👌',
38+
'✌️',
39+
'🤞',
40+
'🤟',
41+
'🤘',
42+
'🤙',
43+
'👈',
44+
'👉',
45+
'👆',
46+
'👇',
47+
'☝️',
48+
'👏',
49+
'🙌',
50+
'👐',
51+
'🤲',
52+
'🤝',
53+
'🙏',
54+
],
55+
动物: [
56+
'🐶',
57+
'🐱',
58+
'🐭',
59+
'🐹',
60+
'🐰',
61+
'🦊',
62+
'🐻',
63+
'🐼',
64+
'🐨',
65+
'🐯',
66+
'🦁',
67+
'🐮',
68+
'🐷',
69+
'🐸',
70+
'🐵',
71+
'🐔',
72+
'🐧',
73+
'🐦',
74+
'🐤',
75+
'🦆',
76+
'🦅',
77+
'🦉',
78+
'🦇',
79+
'🐺',
80+
'🐗',
81+
],
82+
自然: [
83+
'🌸',
84+
'🌺',
85+
'🌻',
86+
'🌷',
87+
'🌹',
88+
'🥀',
89+
'🌼',
90+
'🌱',
91+
'🌿',
92+
'🍀',
93+
'🍃',
94+
'🍂',
95+
'🍁',
96+
'🌾',
97+
'🌵',
98+
'🌴',
99+
'🌳',
100+
'🌲',
101+
'☘️',
102+
'🎋',
103+
'🎍',
104+
'🌾',
105+
],
106+
食物: [
107+
'🍎',
108+
'🍊',
109+
'🍋',
110+
'🍌',
111+
'🍉',
112+
'🍇',
113+
'🍓',
114+
'🍈',
115+
'🍒',
116+
'🍑',
117+
'🥭',
118+
'🍍',
119+
'🥥',
120+
'🥝',
121+
'🍅',
122+
'🥑',
123+
'🍆',
124+
'🌽',
125+
'🌶️',
126+
'🥒',
127+
'🥬',
128+
'🥦',
129+
'🍄',
130+
'🥜',
131+
'🌰',
132+
],
133+
活动: [
134+
'⚽',
135+
'🏀',
136+
'🏈',
137+
'⚾',
138+
'🥎',
139+
'🎾',
140+
'🏐',
141+
'🏉',
142+
'🥏',
143+
'🎱',
144+
'🏓',
145+
'🏸',
146+
'🏒',
147+
'🏑',
148+
'🥍',
149+
'🏏',
150+
'🥅',
151+
'⛳',
152+
'🏹',
153+
'🎣',
154+
'🤿',
155+
'🥊',
156+
'🥋',
157+
'🎽',
158+
'🛹',
159+
],
160+
物品: [
161+
'⌚',
162+
'📱',
163+
'💻',
164+
'⌨️',
165+
'🖥️',
166+
'🖨️',
167+
'🖱️',
168+
'💾',
169+
'💿',
170+
'📀',
171+
'📷',
172+
'📹',
173+
'🎥',
174+
'📞',
175+
'☎️',
176+
'📟',
177+
'📠',
178+
'📺',
179+
'📻',
180+
'🎙️',
181+
'🎚️',
182+
'🎛️',
183+
'⏱️',
184+
'⏰',
185+
'⏲️',
186+
],
187+
符号: [
188+
'❤️',
189+
'🧡',
190+
'💛',
191+
'💚',
192+
'💙',
193+
'💜',
194+
'🖤',
195+
'🤍',
196+
'🤎',
197+
'💔',
198+
'❣️',
199+
'💕',
200+
'💞',
201+
'💓',
202+
'💗',
203+
'💖',
204+
'💘',
205+
'💝',
206+
'✨',
207+
'⭐',
208+
'🌟',
209+
'💫',
210+
'✔️',
211+
'❌',
212+
'⚠️',
213+
],
214+
}
215+
216+
export const EmojiPicker = defineComponent({
217+
name: 'EmojiPicker',
218+
props: {
219+
onSelect: {
220+
type: Function as PropType<(emoji: string) => void>,
221+
required: true,
222+
},
223+
},
224+
setup(props) {
225+
const handleEmojiClick = (emoji: string) => {
226+
props.onSelect(emoji)
227+
}
228+
229+
return () => (
230+
<div class="emoji-picker max-h-96 w-80 rounded-lg bg-white shadow-lg dark:bg-gray-800">
231+
<NScrollbar style={{ maxHeight: '24rem' }}>
232+
<div class="p-3">
233+
{Object.entries(EMOJI_GROUPS).map(([groupName, emojis]) => (
234+
<div key={groupName} class="mb-4">
235+
<div class="mb-2 text-xs font-medium text-gray-500 dark:text-gray-400">
236+
{groupName}
237+
</div>
238+
<div class="grid grid-cols-8 gap-1">
239+
{emojis.map((emoji) => (
240+
<button
241+
key={emoji}
242+
onClick={() => handleEmojiClick(emoji)}
243+
class="emoji-button flex h-8 w-8 cursor-pointer items-center justify-center rounded text-lg transition-colors hover:bg-gray-100 dark:hover:bg-gray-700"
244+
>
245+
{emoji}
246+
</button>
247+
))}
248+
</div>
249+
</div>
250+
))}
251+
</div>
252+
</NScrollbar>
253+
254+
<style>
255+
{`
256+
.emoji-button {
257+
border: none;
258+
background: transparent;
259+
user-select: none;
260+
}
261+
.emoji-button:active {
262+
transform: scale(0.95);
263+
}
264+
`}
265+
</style>
266+
</div>
267+
)
268+
},
269+
})
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { MarkdownToolbar } from './toolbar'
2+
export { EmojiPicker } from './emoji-picker'
3+
export { commands } from './markdown-commands'
4+
export { createToolbarKeymapExtension } from './keymap-extension'

0 commit comments

Comments
 (0)