ToolJet/frontend/src/Editor/Components/CodeEditor.jsx

94 lines
3.3 KiB
React
Raw Normal View History

import React, { useEffect, useState } from 'react';
import { resolveWidgetFieldValue } from '@/_helpers/utils';
import CodeMirror from '@uiw/react-codemirror';
import 'codemirror/addon/comment/comment';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/display/placeholder';
import 'codemirror/addon/search/match-highlighter';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/theme/base16-light.css';
import 'codemirror/theme/duotone-light.css';
import 'codemirror/theme/monokai.css';
import { onBeforeChange, handleChange } from '../CodeBuilder/utils';
export const CodeEditor = ({ width, height, component, currentState, onComponentOptionChanged, darkMode }) => {
const enableLineNumber = component.definition.properties?.enableLineNumber?.value ?? true;
const languageMode = component.definition.properties.mode.value;
const placeholder = component.definition.properties.placeholder.value;
const widgetVisibility = component.definition.styles?.visibility?.value ?? true;
const disabledState = component.definition.styles?.disabledState?.value ?? false;
const parsedDisabledState =
typeof disabledState !== 'boolean' ? resolveWidgetFieldValue(disabledState, currentState) : disabledState;
const parsedWidgetVisibility =
typeof widgetVisibility !== 'boolean' ? resolveWidgetFieldValue(widgetVisibility, currentState) : widgetVisibility;
const parsedEnableLineNumber =
typeof enableLineNumber !== 'boolean' ? resolveWidgetFieldValue(enableLineNumber, currentState) : enableLineNumber;
const value = currentState?.components[component?.name]?.value;
const [editorValue, setEditorValue] = useState(value);
const [realState, setRealState] = useState(currentState);
function codeChanged(code) {
setEditorValue(code);
onComponentOptionChanged(component, 'value', code);
}
const styles = {
height: height,
display: !parsedWidgetVisibility ? 'none' : 'block',
};
const options = {
lineNumbers: parsedEnableLineNumber,
lineWrapping: true,
singleLine: true,
mode: languageMode,
tabSize: 2,
theme: darkMode ? 'monokai' : 'duotone-light',
readOnly: false,
highlightSelectionMatches: true,
placeholder,
};
function valueChanged(editor, onChange, ignoreBraces = false) {
handleChange(editor, onChange, [], ignoreBraces);
setEditorValue(editor.getValue());
}
useEffect(() => {
setRealState(currentState);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentState.components]);
return (
<div data-disabled={parsedDisabledState} style={styles}>
<div
className={`code-hinter codehinter-default-input code-editor-widget`}
style={{
height: height || 'auto',
minHeight: height - 1,
maxHeight: '320px',
overflow: 'auto',
}}
>
<CodeMirror
value={editorValue}
realState={realState}
scrollbarStyle={null}
height={height - 1}
onBlur={(editor) => {
const value = editor.getValue();
codeChanged(value);
}}
onChange={(editor) => valueChanged(editor, codeChanged)}
onBeforeChange={(editor, change) => onBeforeChange(editor, change)}
options={options}
/>
</div>
</div>
);
};