feat: add react types to codeeditor

This commit is contained in:
Khairul Hidayat 2024-03-12 01:56:50 +00:00
parent 7c187452f9
commit bbc4315576
2 changed files with 72 additions and 4 deletions

View File

@ -11,6 +11,11 @@ import { useDebounce } from "~/hooks/useDebounce";
import useCommandKey from "~/hooks/useCommandKey";
import { getFileExt, toast } from "~/lib/utils";
type InitFileData = {
path: string;
value: string;
};
type Props = {
filename?: string;
path?: string;
@ -19,17 +24,28 @@ type Props = {
onChange: (val: string) => void;
formatOnSave?: boolean;
isReadOnly?: boolean;
initialFiles?: InitFileData[];
};
const CodeEditor = (props: Props) => {
const { filename, path, value, formatOnSave, isReadOnly, onChange } = props;
const {
filename,
path,
value,
formatOnSave,
isReadOnly,
onChange,
initialFiles,
} = props;
const editorRef = useRef<any>(null);
const monacoRef = useRef<any>(null);
const [isMounted, setMounted] = useState(false);
const [debounceChange, resetDebounceChange] = useDebounce(onChange, 3000);
const language = useMemo(() => getLanguage(filename), [filename]);
const onMount = useCallback((editor: any, monaco: any) => {
editorRef.current = editor;
monacoRef.current = monaco;
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.Latest,
@ -44,15 +60,33 @@ const CodeEditor = (props: Props) => {
allowJs: true,
typeRoots: ["node_modules/@types"],
});
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
});
setMounted(true);
loadExternalLibs(monaco);
}, []);
useEffect(() => {
const monaco = monacoRef.current;
if (!isMounted || !monaco || !initialFiles?.length) {
return;
}
initialFiles.forEach((i) => {
const uri = monaco.Uri.parse(i.path);
const existingModel = monaco.editor.getModel(uri);
if (!existingModel) {
const lang = getLanguage(i.path);
monaco.editor.createModel(i.value, lang?.name || "", uri);
}
});
}, [initialFiles, isMounted]);
const onSave = useCallback(async () => {
if (isReadOnly) {
return;
@ -239,4 +273,24 @@ function getLanguage(filename?: string | null) {
return { name, formatter };
}
const loadExternalLibs = async (monaco: any) => {
const libs = [
{
name: "react",
url: "https://unpkg.com/@types/react@18.2.65/index.d.ts",
uri: "file:///node_modules/@types/react/index.d.ts",
},
];
libs.forEach(async (lib) => {
try {
const res = await fetch(lib.url);
const data = await res.text();
monaco.languages.typescript.typescriptDefaults.addExtraLib(data, lib.uri);
} catch (err) {
console.error(`Cannot load ${lib.name} lib!`, err);
}
});
};
export default CodeEditor;

View File

@ -4,8 +4,9 @@ import { Data } from "../+data";
import Spinner from "~/components/ui/spinner";
import { previewStore } from "../stores/web-preview";
import { useProjectContext } from "../context/project";
import { Suspense, lazy } from "react";
import { Suspense, lazy, useMemo } from "react";
import CodeEditor from "~/components/ui/code-editor";
import { getFileExt } from "~/lib/utils";
// const CodeEditor = lazy(() => import("~/components/ui/code-editor"));
type Props = {
@ -14,7 +15,7 @@ type Props = {
const FileViewer = ({ id }: Props) => {
const { project } = useProjectContext();
const { initialFiles } = useData<Data>();
const { initialFiles, files } = useData<Data>();
const initialData = initialFiles.find((i) => i.id === id) as any;
const { data, isLoading } = trpc.file.getById.useQuery(id, {
@ -32,6 +33,18 @@ const FileViewer = ({ id }: Props) => {
},
});
const projectJsFiles = useMemo(() => {
return files
.filter((i) => {
const ext = getFileExt(i.filename);
return ["js", "jsx", "ts", "tsx"].includes(ext) && !i.isFile;
})
.map((i) => ({
path: i.path,
value: i.content || "",
}));
}, [files]);
if (isLoading) {
return <LoadingLayout />;
}
@ -49,6 +62,7 @@ const FileViewer = ({ id }: Props) => {
value={data.content || ""}
isReadOnly={!project.isMutable}
formatOnSave
initialFiles={projectJsFiles}
onChange={(val) => {
if (!project.isMutable) {
return;