Add features & update project
This commit is contained in:
@@ -5,6 +5,8 @@ import dynamic from 'next/dynamic';
|
||||
|
||||
import { Button, Switch } from '@spoon/ui';
|
||||
|
||||
import { languageForPath } from './languages';
|
||||
|
||||
const MonacoEditor = dynamic(async () => await import('@monaco-editor/react'), {
|
||||
ssr: false,
|
||||
});
|
||||
@@ -20,27 +22,27 @@ type VimMode = {
|
||||
export const CodeEditor = ({
|
||||
path,
|
||||
content,
|
||||
savedContent,
|
||||
readOnly,
|
||||
vimEnabled,
|
||||
onSave,
|
||||
onChange,
|
||||
onVimEnabledChange,
|
||||
}: {
|
||||
path?: string;
|
||||
content: string;
|
||||
savedContent: string;
|
||||
readOnly: boolean;
|
||||
vimEnabled: boolean;
|
||||
onSave: (content: string) => Promise<void>;
|
||||
onChange: (content: string) => void;
|
||||
onVimEnabledChange: (enabled: boolean) => void;
|
||||
}) => {
|
||||
const [value, setValue] = useState(content);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [vimEnabled, setVimEnabled] = useState(false);
|
||||
const [dirty, setDirty] = useState(false);
|
||||
const editorRef = useRef<MonacoEditorInstance | null>(null);
|
||||
const vimRef = useRef<VimMode | null>(null);
|
||||
const statusRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(content);
|
||||
setDirty(false);
|
||||
}, [content, path]);
|
||||
|
||||
useEffect(() => {
|
||||
const editor = editorRef.current;
|
||||
if (!editor) return;
|
||||
@@ -71,13 +73,14 @@ export const CodeEditor = ({
|
||||
const save = async () => {
|
||||
setSaving(true);
|
||||
try {
|
||||
await onSave(value);
|
||||
setDirty(false);
|
||||
await onSave(content);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const dirty = content !== savedContent;
|
||||
|
||||
return (
|
||||
<div className='flex h-full min-h-0 flex-col'>
|
||||
<div className='border-border flex h-11 items-center justify-between gap-3 border-b px-3'>
|
||||
@@ -90,7 +93,7 @@ export const CodeEditor = ({
|
||||
<div className='flex items-center gap-3'>
|
||||
<label className='flex items-center gap-2 text-xs'>
|
||||
Vim
|
||||
<Switch checked={vimEnabled} onCheckedChange={setVimEnabled} />
|
||||
<Switch checked={vimEnabled} onCheckedChange={onVimEnabledChange} />
|
||||
</label>
|
||||
<Button
|
||||
type='button'
|
||||
@@ -107,7 +110,8 @@ export const CodeEditor = ({
|
||||
height='100%'
|
||||
width='100%'
|
||||
path={path}
|
||||
value={value}
|
||||
language={languageForPath(path)}
|
||||
value={content}
|
||||
theme='vs-dark'
|
||||
options={{
|
||||
readOnly,
|
||||
@@ -116,13 +120,20 @@ export const CodeEditor = ({
|
||||
scrollBeyondLastLine: false,
|
||||
wordWrap: 'on',
|
||||
automaticLayout: true,
|
||||
scrollbar: { alwaysConsumeMouseWheel: false },
|
||||
quickSuggestions: true,
|
||||
suggestOnTriggerCharacters: true,
|
||||
tabCompletion: 'on',
|
||||
wordBasedSuggestions: 'matchingDocuments',
|
||||
bracketPairColorization: { enabled: true },
|
||||
renderWhitespace: 'selection',
|
||||
}}
|
||||
onMount={(editor) => {
|
||||
editorRef.current = editor as MonacoEditorInstance;
|
||||
}}
|
||||
onChange={(next) => {
|
||||
setValue(next ?? '');
|
||||
setDirty((next ?? '') !== content);
|
||||
const nextValue = next ?? '';
|
||||
onChange(nextValue);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user