import * as React from 'react'; import { autocompletion, completionKeymap, completeFromList, } from '@codemirror/autocomplete'; import type {KeyBinding} from '@codemirror/view'; import ts from 'typescript'; import { createDefaultMapFromCDN, createSystem, createVirtualTypeScriptEnvironment, VirtualTypeScriptEnvironment, } from '@typescript/vfs'; // @ts-ignore TS7016 import lzstring from 'lz-string'; import {useActiveCode, SandpackCodeEditor} from '@codesandbox/sandpack-react'; // @ts-ignore import styleguideTypeDefinitions from '!!raw-loader!../../../../dist/sandbox-types/brainly-style-guide-sandbox.d.ts'; // @ts-ignore import reactTypes from '!!raw-loader!../../../../node_modules/@types/react/index.d.ts'; type CodeEditorPropsType = { code: string; }; const {options: compilerOptions} = ts.convertCompilerOptionsFromJson( {jsx: 'rect'}, '' ); export const CodeEditor = ({code}: CodeEditorPropsType) => { const codeRef = React.useRef(code); const {code: editorCode} = useActiveCode(); const [tsEnv, setTsEnv] = React.useState(); const [extensions, setExtensions] = React.useState(null); React.useEffect(() => { const setup = async () => { const fsMap = await createDefaultMapFromCDN( compilerOptions, ts.version, true, ts, lzstring ); fsMap.set('/brainly-style-guide-sandbox.d.ts', styleguideTypeDefinitions); fsMap.set('/react.d.ts', reactTypes); fsMap.set('index.tsx', codeRef.current); const system = createSystem(fsMap); const env = createVirtualTypeScriptEnvironment( system, ['index.tsx', '/brainly-style-guide-sandbox.d.ts', '/react.d.ts'], ts, compilerOptions ); const extensions = [ autocompletion({ override: [ context => { const {pos} = context; let completions; if (env) { completions = env.languageService.getCompletionsAtPosition( 'index.tsx', pos, {} ); } if (!completions) { return null; } return completeFromList( completions.entries.map(c => ({ type: c.kind, label: c.name, })) )(context); }, ], }), ]; setTsEnv(env); // @ts-ignore TS2345 setExtensions(extensions); }; setup(); }, []); React.useEffect(() => { if (tsEnv && editorCode) { tsEnv.updateFile('index.tsx', `${editorCode}`); } }, [tsEnv, editorCode]); if (!extensions) { return null; } return ( ); };