Files
OpenList-Frontend/src/components/MonacoEditor.tsx
outlook84 ae445dad6b refactor!: improve CDN resource management (#144)
* Add `useCDN` hook for better management of CDN resources.

* Bundle CDN resources (Monaco Editor, KaTeX, Mermaid, Ruffle, etc.) using `vite-plugin-static-copy` into the dist, which can be beneficial for environments with network problems. 

* Add `VITE_LITE` environment for conditional lite version compilation, removing the need for a separate lite branch.

BREAKING CHANGE: The lite branch is no longer needed.
2025-08-06 17:01:54 +08:00

69 lines
1.8 KiB
TypeScript

import { Box } from "@hope-ui/solid"
import { createEffect, createSignal, onCleanup, onMount } from "solid-js"
import { MaybeLoading } from "./FullLoading"
import loader from "@monaco-editor/loader"
import { useCDN } from "~/hooks"
import type * as monacoType from "monaco-editor/esm/vs/editor/editor.api"
export interface MonacoEditorProps {
value: string
onChange?: (value: string) => void
theme: "vs" | "vs-dark"
path?: string
language?: string
}
let monaco: typeof monacoType
export const MonacoEditorLoader = (props: MonacoEditorProps) => {
const { monacoPath } = useCDN()
const [loading, setLoading] = createSignal(true)
loader.config({
paths: {
vs: monacoPath(),
},
})
loader.init().then((m) => {
monaco = m
setLoading(false)
})
return (
<MaybeLoading loading={loading()}>
<MonacoEditor {...props} />
</MaybeLoading>
)
}
export const MonacoEditor = (props: MonacoEditorProps) => {
let monacoEditorDiv: HTMLDivElement
let monacoEditor: monacoType.editor.IStandaloneCodeEditor
let model: monacoType.editor.ITextModel
onMount(() => {
monacoEditor = monaco.editor.create(monacoEditorDiv!, {
value: props.value,
theme: props.theme,
})
model = monaco.editor.createModel(
props.value,
props.language,
props.path ? monaco.Uri.parse(props.path) : undefined,
)
monacoEditor.setModel(model)
monacoEditor.onDidChangeModelContent(() => {
props.onChange?.(monacoEditor.getValue())
})
})
createEffect(() => {
monacoEditor.setValue(props.value)
})
createEffect(() => {
monaco.editor.setTheme(props.theme)
})
onCleanup(() => {
model && model.dispose()
monacoEditor && monacoEditor.dispose()
})
return <Box w="$full" h="70vh" ref={monacoEditorDiv!} />
}