2021-11-15 06:42:02 +00:00
|
|
|
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`}
|
2021-12-10 03:13:05 +00:00
|
|
|
style={{
|
|
|
|
|
height: height || 'auto',
|
|
|
|
|
minHeight: height - 1,
|
|
|
|
|
maxHeight: '320px',
|
|
|
|
|
overflow: 'auto',
|
|
|
|
|
}}
|
2021-11-15 06:42:02 +00:00
|
|
|
>
|
|
|
|
|
<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>
|
|
|
|
|
);
|
|
|
|
|
};
|