Skip to content

Commit 8e93bea

Browse files
authored
feat(editor): components suggestions inside monaco (#21)
1 parent e2a7142 commit 8e93bea

File tree

10 files changed

+474
-7
lines changed

10 files changed

+474
-7
lines changed

src/app/src/components/panel/content/editor/PanelContentEditorCode.vue

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<script setup lang="ts">
22
import { onMounted, ref, shallowRef, watch } from 'vue'
33
import type { DatabasePageItem, DraftItem } from '../../../../types'
4+
import { DraftStatus } from '../../../../types/draft'
45
import type { PropType } from 'vue'
5-
import { setupMonaco, type Editor } from '../../../../utils/monaco'
6+
import { setupMonaco, setupSuggestion, type Editor } from '../../../../utils/monaco/index'
67
import { generateContentFromDocument, generateDocumentFromContent, pickReservedKeysFromDocument } from '../../../../utils/content'
8+
import { useStudio } from '../../../../composables/useStudio'
79
810
const props = defineProps({
911
draftItem: {
@@ -13,15 +15,18 @@ const props = defineProps({
1315
})
1416
1517
const document = defineModel<DatabasePageItem>()
18+
const { mediaTree, host } = useStudio()
1619
1720
const editor = shallowRef<Editor.IStandaloneCodeEditor | null>(null)
1821
const editorRef = ref()
1922
const content = ref<string>('')
2023
const currentDocumentId = ref<string | null>(null)
24+
const localStatus = ref<DraftStatus>(props.draftItem.status)
2125
2226
// Trigger on action events
23-
watch(() => props.draftItem.status, () => {
24-
if (editor.value) {
27+
watch(() => props.draftItem.status, (newStatus) => {
28+
if (editor.value && newStatus !== localStatus.value) {
29+
localStatus.value = newStatus
2530
setContent(props.draftItem.modified as DatabasePageItem)
2631
}
2732
})
@@ -35,6 +40,7 @@ watch(() => document.value?.id, async () => {
3540
3641
onMounted(async () => {
3742
const monaco = await setupMonaco()
43+
setupSuggestion(monaco.monaco, host.meta.components(), mediaTree.root.value)
3844
3945
// create a Monaco editor instance
4046
editor.value = monaco.createEditor(editorRef.value)
@@ -52,6 +58,10 @@ onMounted(async () => {
5258
content.value = newContent
5359
5460
generateDocumentFromContent(document.value!.id, content.value).then((doc) => {
61+
// Update local status
62+
localStatus.value = DraftStatus.Updated
63+
64+
// Update document
5565
document.value = {
5666
...pickReservedKeysFromDocument(props.draftItem.original as DatabasePageItem || document.value!),
5767
...doc,
@@ -68,7 +78,11 @@ function setContent(document: DatabasePageItem) {
6878
content.value = md || ''
6979
7080
if (editor.value && editor.value.getModel()?.getValue() !== md) {
81+
// Keep the cursor position
82+
const position = editor.value.getPosition()
7183
editor.value.getModel()?.setValue(md || '')
84+
// Restore the cursor position
85+
position && editor.value.setPosition(position)
7286
}
7387
7488
currentDocumentId.value = document.id

src/app/src/composables/useHooks.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@ import { createSharedComposable } from '@vueuse/core'
22
import { createHooks } from 'hookable'
33

44
export const useHooks = createSharedComposable(() => {
5-
return createHooks()
5+
return createHooks<{
6+
'studio:draft:document:updated': () => void
7+
'studio:draft:media:updated': () => void
8+
}>()
69
})

src/app/src/composables/useMonacoDiff.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// import { computed, watch, unref } from 'vue'
22
// import type { Ref } from 'vue'
33
// import type { editor as Editor } from 'modern-monaco/editor-core'
4-
// import { setupMonaco, setupTheme, baseEditorOptions } from '../utils/monaco'
4+
// import { setupMonaco, setupTheme, baseEditorOptions } from '../utils/monaco/index'
55

66
// export function useMonacoDiff(target: Ref, options: { original: string, modified: string, language: string, renderSideBySide?: boolean }) {
77
// let monaco: Awaited<ReturnType<typeof setupMonaco>>

src/app/src/composables/useMonacoMinimal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// import type { editor as Editor } from 'modern-monaco/editor-core'
33
// import type { Ref } from 'vue'
44
// import { omit } from '../utils/object'
5-
// import { setupMonaco, setupTheme, baseEditorOptions } from '../utils/monaco'
5+
// import { setupMonaco, setupTheme, baseEditorOptions } from '../utils/monaco/index'
66

77
// export function useMonacoMinimal(target: Ref, options: {
88
// code: string

src/app/src/types/components.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { ComponentData } from 'nuxt-component-meta'
2+
3+
export interface ComponentMeta {
4+
name: string,
5+
path: string,
6+
meta: {
7+
props: ComponentData['meta']['props'],
8+
slots: ComponentData['meta']['slots'],
9+
events: ComponentData['meta']['events'],
10+
},
11+
}

src/app/src/types/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { StudioUser } from './user'
22
import type { DatabaseItem } from './database'
33
import type { RouteLocationNormalized } from 'vue-router'
44
import type { MediaItem } from './media'
5+
import { ComponentMeta } from './components'
56

67
export * from './item'
78
export * from './draft'
@@ -12,8 +13,12 @@ export * from './tree'
1213
export * from './github'
1314
export * from './context'
1415
export * from './content'
16+
export * from './components'
1517

1618
export interface StudioHost {
19+
meta: {
20+
components: () => ComponentMeta[]
21+
}
1722
on: {
1823
routeChange: (fn: (to: RouteLocationNormalized, from: RouteLocationNormalized) => void) => void
1924
mounted: (fn: () => void) => void
@@ -52,7 +57,7 @@ export interface StudioHost {
5257
}
5358
}
5459

55-
export type UseStudioHost = (user: StudioUser) => StudioHost
60+
export type UseStudioHost = () => StudioHost
5661

5762
declare global {
5863
interface Window {

src/app/src/utils/monaco.ts renamed to src/app/src/utils/monaco/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createSingletonPromise } from '@vueuse/core'
22
import type { editor as Editor } from 'modern-monaco/editor-core'
33

4+
export { setupSuggestion } from './mdc-compilation'
45
export type { editor as Editor } from 'modern-monaco/editor-core'
56
export type Monaco = Awaited<ReturnType<typeof import('modern-monaco')['init']>>
67

@@ -21,6 +22,7 @@ export const setupMonaco = createSingletonPromise(async () => {
2122
const monaco: Monaco = await init()
2223

2324
return {
25+
monaco,
2426
editor: monaco.editor,
2527
createEditor: ((domElement, options, override) => {
2628
// Inject the CSS bundle into the DOM

0 commit comments

Comments
 (0)