Files
FastGPT/packages/web/components/common/Textarea/JsonEditor/index.tsx
Archer 34602b25df 4.6.8-alpha (#804)
* perf: redirect request and err log replace

perf: dataset openapi

feat: session

fix: retry input error

feat: 468 doc

sub page

feat: standard sub

perf: rerank tip

perf: rerank tip

perf: api sdk

perf: openapi

sub plan

perf: sub ui

fix: ts

* perf: init log

* fix: variable select

* sub page

* icon

* perf: llm model config

* perf: menu ux

* perf: system store

* perf: publish app name

* fix: init data

* perf: flow edit ux

* fix: value type format and ux

* fix prompt editor default value (#13)

* fix prompt editor default value

* fix prompt editor update when not focus

* add key with variable

---------

Co-authored-by: Archer <545436317@qq.com>

* fix: value type

* doc

* i18n

* import path

* home page

* perf: mongo session running

* fix: ts

* perf: use toast

* perf: flow edit

* perf: sse response

* slider ui

* fetch error

* fix prompt editor rerender when not focus by key defaultvalue (#14)

* perf: prompt editor

* feat: dataset search concat

* perf: doc

* fix:ts

* perf: doc

* fix json editor onblur value (#15)

* faq

* vector model default config

* ipv6

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-02-01 21:57:41 +08:00

135 lines
3.6 KiB
TypeScript

import React from 'react';
import Editor, { loader } from '@monaco-editor/react';
import { useCallback, useRef, useState } from 'react';
import { Box, BoxProps, useToast } from '@chakra-ui/react';
import MyIcon from '../../Icon';
loader.config({
paths: { vs: '/js/monaco-editor.0.43.0' }
});
type Props = Omit<BoxProps, 'onChange' | 'resize' | 'height'> & {
height?: number;
resize?: boolean;
defaultValue?: string;
value?: string;
onChange?: (e: string) => void;
};
const options = {
lineNumbers: 'off',
guides: {
indentation: false
},
automaticLayout: true,
minimap: {
enabled: false
},
scrollbar: {
verticalScrollbarSize: 4,
horizontalScrollbarSize: 8,
alwaysConsumeMouseWheel: false
},
lineNumbersMinChars: 0,
fontSize: 12,
scrollBeyondLastLine: false,
folding: false,
overviewRulerBorder: false,
tabSize: 2
};
const JSONEditor = ({ defaultValue, value, onChange, resize, ...props }: Props) => {
const toast = useToast();
const [height, setHeight] = useState(props.height || 100);
const initialY = useRef(0);
const handleMouseDown = useCallback((e: React.MouseEvent) => {
initialY.current = e.clientY;
const handleMouseMove = (e: MouseEvent) => {
const deltaY = e.clientY - initialY.current;
setHeight((prevHeight) => (prevHeight + deltaY < 100 ? 100 : prevHeight + deltaY));
initialY.current = e.clientY;
};
const handleMouseUp = () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}, []);
return (
<Box position={'relative'}>
{resize && (
<Box
position={'absolute'}
right={'0'}
bottom={'0'}
zIndex={999}
cursor={'ns-resize'}
px={'4px'}
onMouseDown={handleMouseDown}
>
<MyIcon name={'common/editor/resizer'} width={'16px'} height={'16px'} />
</Box>
)}
<Box
borderWidth={'1px'}
borderRadius={'md'}
borderColor={'myGray.200'}
py={2}
{...props}
height={'auto'}
>
<Editor
height={height}
defaultLanguage="json"
options={options as any}
theme={'JSONEditorTheme'}
beforeMount={(monaco) => {
monaco?.editor.defineTheme('JSONEditorTheme', {
base: 'vs',
inherit: true,
rules: [],
colors: {
'editor.background': '#ffffff00',
'editorLineNumber.foreground': '#aaa',
'editorOverviewRuler.border': '#ffffff00',
'editor.lineHighlightBackground': '#F7F8FA',
'scrollbarSlider.background': '#E8EAEC',
'editorIndentGuide.activeBackground': '#ddd',
'editorIndentGuide.background': '#eee'
}
});
}}
defaultValue={defaultValue}
value={value}
onChange={(e) => onChange?.(e || '')}
wrapperProps={{
onBlur: () => {
try {
JSON.parse(value as string);
} catch (error: any) {
toast({
title: 'Invalid JSON',
description: error.message,
position: 'top',
status: 'error',
duration: 3000,
isClosable: true
});
}
}
}}
/>
</Box>
</Box>
);
};
export default React.memo(JSONEditor);