mirror of
https://github.com/khairul169/code-share.git
synced 2025-04-28 08:39:35 +07:00
feat: add react types to codeeditor
This commit is contained in:
parent
7c187452f9
commit
bbc4315576
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user