@coveord/plasma-mantine
Version:
A Plasma flavoured Mantine theme
192 lines (191 loc) • 6.63 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/useParentHeight.js';
import { CopyToClipboard } from '../CopyToClipboard/CopyToClipboard.js';
import CodeEditorClasses from './CodeEditor.module.css';
import { XML } from './languages/xml.js';
import { Search } from './search/Search.js';
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', {
base: 'vs',
inherit: true,
rules: [],
colors: {
'editor.background': theme.colors.gray[0]
}
});
};
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 hasError = !!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, {
...errorProps,
children: error
}) : /*#__PURE__*/ _jsx(Space, {
h: "sm"
});
const _header = _label || _description ? /*#__PURE__*/ _jsxs(Stack, {
gap: "xxs",
children: [
_label,
_description
]
}) : null;
const _buttons = /*#__PURE__*/ _jsxs(Group, {
justify: "right",
gap: "xs",
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.root, {
[CodeEditorClasses.error]: hasError
}, {
[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,
stickyScroll: {
enabled: false
},
tabSize
},
value: _value,
onChange: handleChange,
beforeMount: (monaco)=>{
registerLanguages(monaco);
registerThemes(monaco);
},
onMount: (editor)=>{
editorRef.current = editor;
if (editorHandle) {
editorHandle.current = editor;
}
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, {})
});
const height = Math.max(Number.isNaN(parentHeight) ? 0 : parentHeight, minHeight);
return /*#__PURE__*/ _jsxs(Stack, {
justify: "flex-start",
gap: "sm",
h: height,
mah: maxHeight,
ref: ref,
...others,
children: [
/*#__PURE__*/ _jsxs(Group, {
justify: "space-between",
children: [
_header,
_buttons
]
}),
_editor,
_error
]
});
};
CodeEditor.displayName = 'CodeEditor';
//# sourceMappingURL=CodeEditor.js.map