@coveord/plasma-mantine
Version:
A Plasma flavoured Mantine theme
190 lines (189 loc) • 6.52 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Center, Group, Input, Loader, Space, Stack, px, useMantineColorScheme, useMantineTheme, useProps } from '@mantine/core';
import { useUncontrolled } from '@mantine/hooks';
import Editor, { loader } from '@monaco-editor/react';
import { MarkerSeverity } from 'monaco-editor';
import { useEffect, useRef, useState } from 'react';
import cx from 'clsx';
import { useParentHeight } from '../../hooks';
import { CopyToClipboard } from '../copyToClipboard';
import CodeEditorClasses from './CodeEditor.module.css';
import { XML } from './languages/xml';
import { Search } from './search';
const defaultProps = {
language: 'plaintext',
monacoLoader: 'local',
defaultValue: '',
minHeight: 300
};
export const CodeEditor = (props)=>{
const { language, defaultValue, onChange, onCopy, onSearch, onFocus, value, label, required, labelProps, error, errorProps, description, descriptionProps, minHeight, maxHeight, disabled, monacoLoader, options: { tabSize } = {
tabSize: 2
}, editorHandle, ...others } = useProps('CodeEditor', defaultProps, props);
const [loaded, setLoaded] = useState(false);
const [_value, handleChange] = useUncontrolled({
value,
defaultValue,
onChange,
finalValue: ''
});
const [parentHeight, ref] = useParentHeight();
const editorRef = useRef(null);
const loadLocalMonaco = async ()=>{
const monacoInstance = await import('monaco-editor');
loader.config({
monaco: monacoInstance
});
setLoaded(true);
};
const registerLanguages = (monaco)=>{
if (monaco && language === 'xml') {
XML.register(monaco);
}
};
const registerThemes = (monaco)=>{
monaco.editor.defineTheme('light-disabled', {
base: 'vs',
inherit: true,
rules: [],
colors: {
'editor.background': theme.colors.gray[2]
}
});
monaco.editor.defineTheme('vs-dark-disabled', {
base: 'vs-dark',
inherit: true,
rules: [],
colors: {
'editor.background': theme.colors.navy[7]
}
});
};
const handleSearch = ()=>{
if (editorRef.current) {
editorRef.current.focus();
editorRef.current.trigger('editor', 'actions.find', '');
onSearch?.();
}
};
const [hasMonacoError, setHasMonacoError] = useState(false);
const hasMonacoErrorRef = useRef(false);
hasMonacoErrorRef.current = hasMonacoError;
const renderErrorOutline = !!error || hasMonacoError;
const theme = useMantineTheme();
const { colorScheme } = useMantineColorScheme();
useEffect(()=>{
if (monacoLoader === 'local') {
loadLocalMonaco();
} else {
setLoaded(true);
}
}, []);
const handleValidate = (markers)=>{
setHasMonacoError(markers.some((marker)=>marker.severity === MarkerSeverity.Error));
};
const _label = label ? /*#__PURE__*/ _jsx(Input.Label, {
required: required,
...labelProps,
children: label
}) : null;
const _description = description ? /*#__PURE__*/ _jsx(Input.Description, {
...descriptionProps,
children: description
}) : null;
const _error = error ? /*#__PURE__*/ _jsx(Input.Error, {
mt: "xs",
...errorProps,
children: error
}) : /*#__PURE__*/ _jsx(Space, {
h: "xs"
});
const _header = _label || _description ? /*#__PURE__*/ _jsxs(Box, {
children: [
_label,
_description
]
}) : null;
const _buttons = /*#__PURE__*/ _jsxs(Group, {
justify: "right",
gap: 0,
children: [
/*#__PURE__*/ _jsx(Search, {
handleSearch: handleSearch
}),
/*#__PURE__*/ _jsx(CopyToClipboard, {
value: _value,
onCopy: ()=>onCopy?.()
})
]
});
let editorTheme = colorScheme === 'light' ? 'light' : 'vs-dark';
if (disabled) {
editorTheme += '-disabled';
}
const _editor = loaded ? /*#__PURE__*/ _jsx(Box, {
p: "md",
pl: "xs",
className: cx(CodeEditorClasses.editor, {
[CodeEditorClasses.valid]: !renderErrorOutline
}, {
[CodeEditorClasses.error]: renderErrorOutline
}, {
[CodeEditorClasses.disabled]: disabled
}),
"data-testid": "editor-wrapper",
children: /*#__PURE__*/ _jsx(Editor, {
onValidate: handleValidate,
defaultLanguage: language,
theme: editorTheme,
options: {
minimap: {
enabled: false
},
wordWrap: 'on',
scrollBeyondLastLine: false,
formatOnPaste: true,
fontSize: px(theme.fontSizes.xs),
readOnly: disabled,
tabSize
},
value: _value,
onChange: handleChange,
onMount: (editor, monaco)=>{
editorRef.current = editor;
if (editorHandle) {
editorHandle.current = editor;
}
registerLanguages(monaco);
registerThemes(monaco);
editor.onDidFocusEditorText(()=>onFocus?.());
editor.onDidBlurEditorText(async ()=>{
// monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that
setTimeout(async ()=>{
if (!hasMonacoErrorRef.current) {
await editor?.getAction('editor.action.formatDocument')?.run();
}
}, 550);
});
}
})
}) : /*#__PURE__*/ _jsx(Center, {
className: CodeEditorClasses.editor,
children: /*#__PURE__*/ _jsx(Loader, {})
});
return /*#__PURE__*/ _jsxs(Stack, {
justify: "flex-start",
gap: 0,
h: Math.max(parentHeight, minHeight),
mah: maxHeight,
ref: ref,
...others,
children: [
_header,
_buttons,
_editor,
_error
]
});
};
//# sourceMappingURL=CodeEditor.js.map