@coveord/plasma-mantine 55.7.2 → 55.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +3 -3
- package/.turbo/turbo-test.log +52 -50
- package/dist/.tsbuildinfo +1 -1
- package/dist/cjs/components/code-editor/CodeEditor.d.ts +2 -0
- package/dist/cjs/components/code-editor/CodeEditor.d.ts.map +1 -1
- package/dist/cjs/components/code-editor/CodeEditor.js +8 -3
- package/dist/cjs/components/code-editor/CodeEditor.js.map +1 -1
- package/dist/esm/components/code-editor/CodeEditor.d.ts +2 -0
- package/dist/esm/components/code-editor/CodeEditor.d.ts.map +1 -1
- package/dist/esm/components/code-editor/CodeEditor.js +5 -2
- package/dist/esm/components/code-editor/CodeEditor.js.map +1 -1
- package/package.json +18 -17
- package/src/components/code-editor/CodeEditor.tsx +9 -2
- package/src/components/code-editor/__tests__/CodeEditor.spec.tsx +16 -0
|
@@ -20,6 +20,8 @@ interface CodeEditorProps extends Omit<InputWrapperProps, 'inputContainer' | 'in
|
|
|
20
20
|
onCopy?(): void;
|
|
21
21
|
/** Called whenever the code editor gets the focus */
|
|
22
22
|
onFocus?(): void;
|
|
23
|
+
/** Ref object that provides access to the editor's functionality */
|
|
24
|
+
editorHandle?: React.MutableRefObject<monacoEditor.IStandaloneCodeEditor | null>;
|
|
23
25
|
/**
|
|
24
26
|
* The minimal height of the CodeEditor (label and description included)
|
|
25
27
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKH,iBAAiB,EAIjB,UAAU,EAKb,MAAM,eAAe,CAAC;AAGvB,OAAO,
|
|
1
|
+
{"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKH,iBAAiB,EAIjB,UAAU,EAKb,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAiB,MAAM,IAAI,YAAY,EAAC,MAAM,eAAe,CAAC;AACrE,OAAO,EAAC,iBAAiB,EAA8B,MAAM,OAAO,CAAC;AAQrE,UAAU,eACN,SAAQ,IAAI,CACJ,iBAAiB,EACjB,gBAAgB,GAAG,mBAAmB,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CACzF,EACD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IACrF,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,+CAA+C;IAC/C,MAAM,CAAC,IAAI,IAAI,CAAC;IAChB,qDAAqD;IACrD,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,oEAAoE;IACpE,YAAY,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACjF;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,oCAAoC,EAAE,SAAS,CAAC,CAAC;CAChF;AASD,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CA+LzD,CAAC"}
|
|
@@ -38,7 +38,7 @@ var defaultProps = {
|
|
|
38
38
|
var CodeEditor = function(props) {
|
|
39
39
|
var _useProps = (0, _core.useProps)('CodeEditor', defaultProps, props), language = _useProps.language, defaultValue = _useProps.defaultValue, onChange = _useProps.onChange, onCopy = _useProps.onCopy, onSearch = _useProps.onSearch, onFocus = _useProps.onFocus, value = _useProps.value, label = _useProps.label, required = _useProps.required, labelProps = _useProps.labelProps, error = _useProps.error, errorProps = _useProps.errorProps, description = _useProps.description, descriptionProps = _useProps.descriptionProps, minHeight = _useProps.minHeight, maxHeight = _useProps.maxHeight, disabled = _useProps.disabled, monacoLoader = _useProps.monacoLoader, tmp = _useProps.options, tabSize = (tmp === void 0 ? {
|
|
40
40
|
tabSize: 2
|
|
41
|
-
} : tmp).tabSize, others = _object_without_properties._(_useProps, [
|
|
41
|
+
} : tmp).tabSize, editorHandle = _useProps.editorHandle, others = _object_without_properties._(_useProps, [
|
|
42
42
|
"language",
|
|
43
43
|
"defaultValue",
|
|
44
44
|
"onChange",
|
|
@@ -57,7 +57,8 @@ var CodeEditor = function(props) {
|
|
|
57
57
|
"maxHeight",
|
|
58
58
|
"disabled",
|
|
59
59
|
"monacoLoader",
|
|
60
|
-
"options"
|
|
60
|
+
"options",
|
|
61
|
+
"editorHandle"
|
|
61
62
|
]);
|
|
62
63
|
var _useState = _sliced_to_array._((0, _react1.useState)(false), 2), loaded = _useState[0], setLoaded = _useState[1];
|
|
63
64
|
var _useUncontrolled = _sliced_to_array._((0, _hooks.useUncontrolled)({
|
|
@@ -208,6 +209,9 @@ var CodeEditor = function(props) {
|
|
|
208
209
|
onChange: handleChange,
|
|
209
210
|
onMount: function(editor, monaco) {
|
|
210
211
|
editorRef.current = editor;
|
|
212
|
+
if (editorHandle) {
|
|
213
|
+
editorHandle.current = editor;
|
|
214
|
+
}
|
|
211
215
|
registerLanguages(monaco);
|
|
212
216
|
registerThemes(monaco);
|
|
213
217
|
editor.onDidFocusEditorText(function() {
|
|
@@ -217,6 +221,7 @@ var CodeEditor = function(props) {
|
|
|
217
221
|
return _ts_generator._(this, function(_state) {
|
|
218
222
|
// monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that
|
|
219
223
|
setTimeout(/*#__PURE__*/ _async_to_generator._(function() {
|
|
224
|
+
var _editor_getAction;
|
|
220
225
|
return _ts_generator._(this, function(_state) {
|
|
221
226
|
switch(_state.label){
|
|
222
227
|
case 0:
|
|
@@ -226,7 +231,7 @@ var CodeEditor = function(props) {
|
|
|
226
231
|
];
|
|
227
232
|
return [
|
|
228
233
|
4,
|
|
229
|
-
editor.getAction('editor.action.formatDocument').run()
|
|
234
|
+
editor === null || editor === void 0 ? void 0 : (_editor_getAction = editor.getAction('editor.action.formatDocument')) === null || _editor_getAction === void 0 ? void 0 : _editor_getAction.run()
|
|
230
235
|
];
|
|
231
236
|
case 1:
|
|
232
237
|
_state.sent();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"sourcesContent":["import {\n Box,\n Center,\n Group,\n Input,\n InputWrapperProps,\n Loader,\n Space,\n Stack,\n StackProps,\n px,\n useMantineColorScheme,\n useMantineTheme,\n useProps,\n} from '@mantine/core';\nimport {useUncontrolled} from '@mantine/hooks';\nimport Editor, {Monaco, loader} from '@monaco-editor/react';\nimport {editor as monacoEditor, MarkerSeverity} from 'monaco-editor';\nimport {FunctionComponent, useEffect, useRef, useState} from 'react';\n\nimport cx from 'clsx';\nimport {useParentHeight} from '../../hooks';\nimport {CopyToClipboard} from '../copyToClipboard';\nimport CodeEditorClasses from './CodeEditor.module.css';\nimport {XML} from './languages/xml';\nimport {Search} from './search';\ninterface CodeEditorProps\n extends Omit<\n InputWrapperProps,\n 'inputContainer' | 'inputWrapperOrder' | 'classNames' | 'styles' | 'vars' | 'onChange'\n >,\n Omit<StackProps, 'onChange'> {\n /**\n * The language syntax of the editor\n *\n * @default 'plaintext'\n */\n language?: 'plaintext' | 'json' | 'markdown' | 'python' | 'xml' | (string & unknown);\n /** Default value for uncontrolled input */\n defaultValue?: string;\n /** Value for controlled input */\n value?: string;\n /** onChange value for controlled input */\n onChange?(value: string): void;\n /** Called whenever the search icon is clicked */\n onSearch?(): void;\n /** Called whenever the copy icon is clicked */\n onCopy?(): void;\n /** Called whenever the code editor gets the focus */\n onFocus?(): void;\n /**\n * The minimal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height is too short, it will use this value as minimum.\n *\n * @default 300\n */\n minHeight?: number;\n /**\n * The maximal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height would be too high for your liking, you can use this prop to set a maximum.\n */\n maxHeight?: number;\n disabled?: boolean;\n /**\n * Defines how the monaco editor files will be loaded.\n * Note that using `'local'` requires [some additional configuration](https://github.com/suren-atoyan/monaco-react#use-monaco-editor-as-an-npm-package).\n *\n * @default 'local'\n */\n monacoLoader?: 'cdn' | 'local';\n /**\n * Options to pass to the monaco editor.\n * Currently only supporting [`tabSize`](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html#tabSize).\n *\n */\n options?: Pick<monacoEditor.IStandaloneEditorConstructionOptions, 'tabSize'>;\n}\n\nconst defaultProps: Partial<CodeEditorProps> = {\n language: 'plaintext',\n monacoLoader: 'local',\n defaultValue: '',\n minHeight: 300,\n};\n\nexport const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {\n const {\n language,\n defaultValue,\n onChange,\n onCopy,\n onSearch,\n onFocus,\n value,\n label,\n required,\n labelProps,\n error,\n errorProps,\n description,\n descriptionProps,\n minHeight,\n maxHeight,\n disabled,\n monacoLoader,\n options: {tabSize} = {tabSize: 2},\n ...others\n } = useProps('CodeEditor', defaultProps, props);\n const [loaded, setLoaded] = useState(false);\n const [_value, handleChange] = useUncontrolled<string>({\n value,\n defaultValue,\n onChange,\n finalValue: '',\n });\n const [parentHeight, ref] = useParentHeight();\n const editorRef = useRef(null);\n const loadLocalMonaco = async () => {\n const monacoInstance = await import('monaco-editor');\n loader.config({monaco: monacoInstance});\n setLoaded(true);\n };\n\n const registerLanguages = (monaco: Monaco) => {\n if (monaco && language === 'xml') {\n XML.register(monaco);\n }\n };\n\n const registerThemes = (monaco: Monaco) => {\n monaco.editor.defineTheme('light-disabled', {\n base: 'vs',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.gray[2],\n },\n });\n monaco.editor.defineTheme('vs-dark-disabled', {\n base: 'vs-dark',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.navy[7],\n },\n });\n };\n\n const handleSearch = () => {\n if (editorRef.current) {\n editorRef.current.focus();\n editorRef.current.trigger('editor', 'actions.find', '');\n onSearch?.();\n }\n };\n\n const [hasMonacoError, setHasMonacoError] = useState(false);\n const hasMonacoErrorRef = useRef(false);\n\n hasMonacoErrorRef.current = hasMonacoError;\n\n const renderErrorOutline = !!error || hasMonacoError;\n const theme = useMantineTheme();\n const {colorScheme} = useMantineColorScheme();\n\n useEffect(() => {\n if (monacoLoader === 'local') {\n loadLocalMonaco();\n } else {\n setLoaded(true);\n }\n }, []);\n\n const handleValidate = (markers: monacoEditor.IMarker[]) => {\n setHasMonacoError(markers.some((marker) => marker.severity === MarkerSeverity.Error));\n };\n\n const _label = label ? (\n <Input.Label required={required} {...labelProps}>\n {label}\n </Input.Label>\n ) : null;\n\n const _description = description ? (\n <Input.Description {...descriptionProps}>{description}</Input.Description>\n ) : null;\n\n const _error = error ? (\n <Input.Error mt=\"xs\" {...errorProps}>\n {error}\n </Input.Error>\n ) : (\n <Space h=\"xs\" />\n );\n\n const _header =\n _label || _description ? (\n <Box>\n {_label}\n {_description}\n </Box>\n ) : null;\n\n const _buttons = (\n <Group justify=\"right\" gap={0}>\n <Search handleSearch={handleSearch} />\n <CopyToClipboard value={_value} onCopy={() => onCopy?.()} />\n </Group>\n );\n let editorTheme = colorScheme === 'light' ? 'light' : 'vs-dark';\n if (disabled) {\n editorTheme += '-disabled';\n }\n\n const _editor = loaded ? (\n <Box\n p=\"md\"\n pl=\"xs\"\n className={cx(\n CodeEditorClasses.editor,\n {[CodeEditorClasses.valid]: !renderErrorOutline},\n {[CodeEditorClasses.error]: renderErrorOutline},\n {[CodeEditorClasses.disabled]: disabled},\n )}\n data-testid=\"editor-wrapper\"\n >\n <Editor\n onValidate={handleValidate}\n defaultLanguage={language}\n theme={editorTheme}\n options={{\n minimap: {enabled: false},\n wordWrap: 'on',\n scrollBeyondLastLine: false,\n formatOnPaste: true,\n fontSize: px(theme.fontSizes.xs) as number,\n readOnly: disabled,\n tabSize,\n }}\n value={_value}\n onChange={handleChange}\n onMount={(editor, monaco) => {\n editorRef.current = editor;\n registerLanguages(monaco);\n registerThemes(monaco);\n editor.onDidFocusEditorText(() => onFocus?.());\n editor.onDidBlurEditorText(async () => {\n // monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that\n setTimeout(async () => {\n if (!hasMonacoErrorRef.current) {\n await editor.getAction('editor.action.formatDocument').run();\n }\n }, 550);\n });\n }}\n />\n </Box>\n ) : (\n <Center className={CodeEditorClasses.editor}>\n <Loader />\n </Center>\n );\n\n return (\n <Stack justify=\"flex-start\" gap={0} h={Math.max(parentHeight, minHeight)} mah={maxHeight} ref={ref} {...others}>\n {_header}\n {_buttons}\n {_editor}\n {_error}\n </Stack>\n );\n};\n"],"names":["CodeEditor","defaultProps","language","monacoLoader","defaultValue","minHeight","props","useProps","onChange","onCopy","onSearch","onFocus","value","label","required","labelProps","error","errorProps","description","descriptionProps","maxHeight","disabled","options","tabSize","others","useState","loaded","setLoaded","useUncontrolled","finalValue","_value","handleChange","useParentHeight","parentHeight","ref","editorRef","useRef","loadLocalMonaco","monacoInstance","loader","config","monaco","registerLanguages","XML","register","registerThemes","editor","defineTheme","base","inherit","rules","colors","theme","gray","navy","handleSearch","current","focus","trigger","hasMonacoError","setHasMonacoError","hasMonacoErrorRef","renderErrorOutline","useMantineTheme","colorScheme","useMantineColorScheme","useEffect","handleValidate","markers","some","marker","severity","MarkerSeverity","Error","_label","Input","Label","_description","Description","_error","mt","Space","h","_header","Box","_buttons","Group","justify","gap","Search","CopyToClipboard","editorTheme","_editor","p","pl","className","cx","CodeEditorClasses","valid","data-testid","Editor","onValidate","defaultLanguage","minimap","enabled","wordWrap","scrollBeyondLastLine","formatOnPaste","fontSize","px","fontSizes","xs","readOnly","onMount","onDidFocusEditorText","onDidBlurEditorText","setTimeout","getAction","run","Center","Loader","Stack","Math","max","mah"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"sourcesContent":["import {\n Box,\n Center,\n Group,\n Input,\n InputWrapperProps,\n Loader,\n Space,\n Stack,\n StackProps,\n px,\n useMantineColorScheme,\n useMantineTheme,\n useProps,\n} from '@mantine/core';\nimport {useUncontrolled} from '@mantine/hooks';\nimport Editor, {Monaco, loader} from '@monaco-editor/react';\nimport {MarkerSeverity, editor as monacoEditor} from 'monaco-editor';\nimport {FunctionComponent, useEffect, useRef, useState} from 'react';\n\nimport cx from 'clsx';\nimport {useParentHeight} from '../../hooks';\nimport {CopyToClipboard} from '../copyToClipboard';\nimport CodeEditorClasses from './CodeEditor.module.css';\nimport {XML} from './languages/xml';\nimport {Search} from './search';\ninterface CodeEditorProps\n extends Omit<\n InputWrapperProps,\n 'inputContainer' | 'inputWrapperOrder' | 'classNames' | 'styles' | 'vars' | 'onChange'\n >,\n Omit<StackProps, 'onChange'> {\n /**\n * The language syntax of the editor\n *\n * @default 'plaintext'\n */\n language?: 'plaintext' | 'json' | 'markdown' | 'python' | 'xml' | (string & unknown);\n /** Default value for uncontrolled input */\n defaultValue?: string;\n /** Value for controlled input */\n value?: string;\n /** onChange value for controlled input */\n onChange?(value: string): void;\n /** Called whenever the search icon is clicked */\n onSearch?(): void;\n /** Called whenever the copy icon is clicked */\n onCopy?(): void;\n /** Called whenever the code editor gets the focus */\n onFocus?(): void;\n /** Ref object that provides access to the editor's functionality */\n editorHandle?: React.MutableRefObject<monacoEditor.IStandaloneCodeEditor | null>;\n /**\n * The minimal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height is too short, it will use this value as minimum.\n *\n * @default 300\n */\n minHeight?: number;\n /**\n * The maximal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height would be too high for your liking, you can use this prop to set a maximum.\n */\n maxHeight?: number;\n disabled?: boolean;\n /**\n * Defines how the monaco editor files will be loaded.\n * Note that using `'local'` requires [some additional configuration](https://github.com/suren-atoyan/monaco-react#use-monaco-editor-as-an-npm-package).\n *\n * @default 'local'\n */\n monacoLoader?: 'cdn' | 'local';\n /**\n * Options to pass to the monaco editor.\n * Currently only supporting [`tabSize`](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html#tabSize).\n *\n */\n options?: Pick<monacoEditor.IStandaloneEditorConstructionOptions, 'tabSize'>;\n}\n\nconst defaultProps: Partial<CodeEditorProps> = {\n language: 'plaintext',\n monacoLoader: 'local',\n defaultValue: '',\n minHeight: 300,\n};\n\nexport const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {\n const {\n language,\n defaultValue,\n onChange,\n onCopy,\n onSearch,\n onFocus,\n value,\n label,\n required,\n labelProps,\n error,\n errorProps,\n description,\n descriptionProps,\n minHeight,\n maxHeight,\n disabled,\n monacoLoader,\n options: {tabSize} = {tabSize: 2},\n editorHandle,\n ...others\n } = useProps('CodeEditor', defaultProps, props);\n const [loaded, setLoaded] = useState(false);\n const [_value, handleChange] = useUncontrolled<string>({\n value,\n defaultValue,\n onChange,\n finalValue: '',\n });\n const [parentHeight, ref] = useParentHeight();\n const editorRef = useRef(null);\n\n const loadLocalMonaco = async () => {\n const monacoInstance = await import('monaco-editor');\n loader.config({monaco: monacoInstance});\n setLoaded(true);\n };\n\n const registerLanguages = (monaco: Monaco) => {\n if (monaco && language === 'xml') {\n XML.register(monaco);\n }\n };\n\n const registerThemes = (monaco: Monaco) => {\n monaco.editor.defineTheme('light-disabled', {\n base: 'vs',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.gray[2],\n },\n });\n monaco.editor.defineTheme('vs-dark-disabled', {\n base: 'vs-dark',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.navy[7],\n },\n });\n };\n\n const handleSearch = () => {\n if (editorRef.current) {\n editorRef.current.focus();\n editorRef.current.trigger('editor', 'actions.find', '');\n onSearch?.();\n }\n };\n\n const [hasMonacoError, setHasMonacoError] = useState(false);\n const hasMonacoErrorRef = useRef(false);\n\n hasMonacoErrorRef.current = hasMonacoError;\n\n const renderErrorOutline = !!error || hasMonacoError;\n const theme = useMantineTheme();\n const {colorScheme} = useMantineColorScheme();\n\n useEffect(() => {\n if (monacoLoader === 'local') {\n loadLocalMonaco();\n } else {\n setLoaded(true);\n }\n }, []);\n\n const handleValidate = (markers: monacoEditor.IMarker[]) => {\n setHasMonacoError(markers.some((marker) => marker.severity === MarkerSeverity.Error));\n };\n\n const _label = label ? (\n <Input.Label required={required} {...labelProps}>\n {label}\n </Input.Label>\n ) : null;\n\n const _description = description ? (\n <Input.Description {...descriptionProps}>{description}</Input.Description>\n ) : null;\n\n const _error = error ? (\n <Input.Error mt=\"xs\" {...errorProps}>\n {error}\n </Input.Error>\n ) : (\n <Space h=\"xs\" />\n );\n\n const _header =\n _label || _description ? (\n <Box>\n {_label}\n {_description}\n </Box>\n ) : null;\n\n const _buttons = (\n <Group justify=\"right\" gap={0}>\n <Search handleSearch={handleSearch} />\n <CopyToClipboard value={_value} onCopy={() => onCopy?.()} />\n </Group>\n );\n let editorTheme = colorScheme === 'light' ? 'light' : 'vs-dark';\n if (disabled) {\n editorTheme += '-disabled';\n }\n\n const _editor = loaded ? (\n <Box\n p=\"md\"\n pl=\"xs\"\n className={cx(\n CodeEditorClasses.editor,\n {[CodeEditorClasses.valid]: !renderErrorOutline},\n {[CodeEditorClasses.error]: renderErrorOutline},\n {[CodeEditorClasses.disabled]: disabled},\n )}\n data-testid=\"editor-wrapper\"\n >\n <Editor\n onValidate={handleValidate}\n defaultLanguage={language}\n theme={editorTheme}\n options={{\n minimap: {enabled: false},\n wordWrap: 'on',\n scrollBeyondLastLine: false,\n formatOnPaste: true,\n fontSize: px(theme.fontSizes.xs) as number,\n readOnly: disabled,\n tabSize,\n }}\n value={_value}\n onChange={handleChange}\n onMount={(editor, monaco) => {\n editorRef.current = editor;\n if (editorHandle) {\n editorHandle.current = editor;\n }\n registerLanguages(monaco);\n registerThemes(monaco);\n editor.onDidFocusEditorText(() => onFocus?.());\n editor.onDidBlurEditorText(async () => {\n // monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that\n setTimeout(async () => {\n if (!hasMonacoErrorRef.current) {\n await editor?.getAction('editor.action.formatDocument')?.run();\n }\n }, 550);\n });\n }}\n />\n </Box>\n ) : (\n <Center className={CodeEditorClasses.editor}>\n <Loader />\n </Center>\n );\n\n return (\n <Stack justify=\"flex-start\" gap={0} h={Math.max(parentHeight, minHeight)} mah={maxHeight} ref={ref} {...others}>\n {_header}\n {_buttons}\n {_editor}\n {_error}\n </Stack>\n );\n};\n"],"names":["CodeEditor","defaultProps","language","monacoLoader","defaultValue","minHeight","props","useProps","onChange","onCopy","onSearch","onFocus","value","label","required","labelProps","error","errorProps","description","descriptionProps","maxHeight","disabled","options","tabSize","editorHandle","others","useState","loaded","setLoaded","useUncontrolled","finalValue","_value","handleChange","useParentHeight","parentHeight","ref","editorRef","useRef","loadLocalMonaco","monacoInstance","loader","config","monaco","registerLanguages","XML","register","registerThemes","editor","defineTheme","base","inherit","rules","colors","theme","gray","navy","handleSearch","current","focus","trigger","hasMonacoError","setHasMonacoError","hasMonacoErrorRef","renderErrorOutline","useMantineTheme","colorScheme","useMantineColorScheme","useEffect","handleValidate","markers","some","marker","severity","MarkerSeverity","Error","_label","Input","Label","_description","Description","_error","mt","Space","h","_header","Box","_buttons","Group","justify","gap","Search","CopyToClipboard","editorTheme","_editor","p","pl","className","cx","CodeEditorClasses","valid","data-testid","Editor","onValidate","defaultLanguage","minimap","enabled","wordWrap","scrollBeyondLastLine","formatOnPaste","fontSize","px","fontSizes","xs","readOnly","onMount","onDidFocusEditorText","onDidBlurEditorText","setTimeout","getAction","run","Center","Loader","Stack","Math","max","mah"],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ interface CodeEditorProps extends Omit<InputWrapperProps, 'inputContainer' | 'in
|
|
|
20
20
|
onCopy?(): void;
|
|
21
21
|
/** Called whenever the code editor gets the focus */
|
|
22
22
|
onFocus?(): void;
|
|
23
|
+
/** Ref object that provides access to the editor's functionality */
|
|
24
|
+
editorHandle?: React.MutableRefObject<monacoEditor.IStandaloneCodeEditor | null>;
|
|
23
25
|
/**
|
|
24
26
|
* The minimal height of the CodeEditor (label and description included)
|
|
25
27
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKH,iBAAiB,EAIjB,UAAU,EAKb,MAAM,eAAe,CAAC;AAGvB,OAAO,
|
|
1
|
+
{"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKH,iBAAiB,EAIjB,UAAU,EAKb,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAiB,MAAM,IAAI,YAAY,EAAC,MAAM,eAAe,CAAC;AACrE,OAAO,EAAC,iBAAiB,EAA8B,MAAM,OAAO,CAAC;AAQrE,UAAU,eACN,SAAQ,IAAI,CACJ,iBAAiB,EACjB,gBAAgB,GAAG,mBAAmB,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CACzF,EACD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IACrF,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,+CAA+C;IAC/C,MAAM,CAAC,IAAI,IAAI,CAAC;IAChB,qDAAqD;IACrD,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,oEAAoE;IACpE,YAAY,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACjF;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,oCAAoC,EAAE,SAAS,CAAC,CAAC;CAChF;AASD,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CA+LzD,CAAC"}
|
|
@@ -19,7 +19,7 @@ const defaultProps = {
|
|
|
19
19
|
export const CodeEditor = (props)=>{
|
|
20
20
|
const { language, defaultValue, onChange, onCopy, onSearch, onFocus, value, label, required, labelProps, error, errorProps, description, descriptionProps, minHeight, maxHeight, disabled, monacoLoader, options: { tabSize } = {
|
|
21
21
|
tabSize: 2
|
|
22
|
-
}, ...others } = useProps('CodeEditor', defaultProps, props);
|
|
22
|
+
}, editorHandle, ...others } = useProps('CodeEditor', defaultProps, props);
|
|
23
23
|
const [loaded, setLoaded] = useState(false);
|
|
24
24
|
const [_value, handleChange] = useUncontrolled({
|
|
25
25
|
value,
|
|
@@ -151,6 +151,9 @@ export const CodeEditor = (props)=>{
|
|
|
151
151
|
onChange: handleChange,
|
|
152
152
|
onMount: (editor, monaco)=>{
|
|
153
153
|
editorRef.current = editor;
|
|
154
|
+
if (editorHandle) {
|
|
155
|
+
editorHandle.current = editor;
|
|
156
|
+
}
|
|
154
157
|
registerLanguages(monaco);
|
|
155
158
|
registerThemes(monaco);
|
|
156
159
|
editor.onDidFocusEditorText(()=>onFocus?.());
|
|
@@ -158,7 +161,7 @@ export const CodeEditor = (props)=>{
|
|
|
158
161
|
// monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that
|
|
159
162
|
setTimeout(async ()=>{
|
|
160
163
|
if (!hasMonacoErrorRef.current) {
|
|
161
|
-
await editor
|
|
164
|
+
await editor?.getAction('editor.action.formatDocument')?.run();
|
|
162
165
|
}
|
|
163
166
|
}, 550);
|
|
164
167
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"sourcesContent":["import {\n Box,\n Center,\n Group,\n Input,\n InputWrapperProps,\n Loader,\n Space,\n Stack,\n StackProps,\n px,\n useMantineColorScheme,\n useMantineTheme,\n useProps,\n} from '@mantine/core';\nimport {useUncontrolled} from '@mantine/hooks';\nimport Editor, {Monaco, loader} from '@monaco-editor/react';\nimport {editor as monacoEditor, MarkerSeverity} from 'monaco-editor';\nimport {FunctionComponent, useEffect, useRef, useState} from 'react';\n\nimport cx from 'clsx';\nimport {useParentHeight} from '../../hooks';\nimport {CopyToClipboard} from '../copyToClipboard';\nimport CodeEditorClasses from './CodeEditor.module.css';\nimport {XML} from './languages/xml';\nimport {Search} from './search';\ninterface CodeEditorProps\n extends Omit<\n InputWrapperProps,\n 'inputContainer' | 'inputWrapperOrder' | 'classNames' | 'styles' | 'vars' | 'onChange'\n >,\n Omit<StackProps, 'onChange'> {\n /**\n * The language syntax of the editor\n *\n * @default 'plaintext'\n */\n language?: 'plaintext' | 'json' | 'markdown' | 'python' | 'xml' | (string & unknown);\n /** Default value for uncontrolled input */\n defaultValue?: string;\n /** Value for controlled input */\n value?: string;\n /** onChange value for controlled input */\n onChange?(value: string): void;\n /** Called whenever the search icon is clicked */\n onSearch?(): void;\n /** Called whenever the copy icon is clicked */\n onCopy?(): void;\n /** Called whenever the code editor gets the focus */\n onFocus?(): void;\n /**\n * The minimal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height is too short, it will use this value as minimum.\n *\n * @default 300\n */\n minHeight?: number;\n /**\n * The maximal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height would be too high for your liking, you can use this prop to set a maximum.\n */\n maxHeight?: number;\n disabled?: boolean;\n /**\n * Defines how the monaco editor files will be loaded.\n * Note that using `'local'` requires [some additional configuration](https://github.com/suren-atoyan/monaco-react#use-monaco-editor-as-an-npm-package).\n *\n * @default 'local'\n */\n monacoLoader?: 'cdn' | 'local';\n /**\n * Options to pass to the monaco editor.\n * Currently only supporting [`tabSize`](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html#tabSize).\n *\n */\n options?: Pick<monacoEditor.IStandaloneEditorConstructionOptions, 'tabSize'>;\n}\n\nconst defaultProps: Partial<CodeEditorProps> = {\n language: 'plaintext',\n monacoLoader: 'local',\n defaultValue: '',\n minHeight: 300,\n};\n\nexport const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {\n const {\n language,\n defaultValue,\n onChange,\n onCopy,\n onSearch,\n onFocus,\n value,\n label,\n required,\n labelProps,\n error,\n errorProps,\n description,\n descriptionProps,\n minHeight,\n maxHeight,\n disabled,\n monacoLoader,\n options: {tabSize} = {tabSize: 2},\n ...others\n } = useProps('CodeEditor', defaultProps, props);\n const [loaded, setLoaded] = useState(false);\n const [_value, handleChange] = useUncontrolled<string>({\n value,\n defaultValue,\n onChange,\n finalValue: '',\n });\n const [parentHeight, ref] = useParentHeight();\n const editorRef = useRef(null);\n const loadLocalMonaco = async () => {\n const monacoInstance = await import('monaco-editor');\n loader.config({monaco: monacoInstance});\n setLoaded(true);\n };\n\n const registerLanguages = (monaco: Monaco) => {\n if (monaco && language === 'xml') {\n XML.register(monaco);\n }\n };\n\n const registerThemes = (monaco: Monaco) => {\n monaco.editor.defineTheme('light-disabled', {\n base: 'vs',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.gray[2],\n },\n });\n monaco.editor.defineTheme('vs-dark-disabled', {\n base: 'vs-dark',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.navy[7],\n },\n });\n };\n\n const handleSearch = () => {\n if (editorRef.current) {\n editorRef.current.focus();\n editorRef.current.trigger('editor', 'actions.find', '');\n onSearch?.();\n }\n };\n\n const [hasMonacoError, setHasMonacoError] = useState(false);\n const hasMonacoErrorRef = useRef(false);\n\n hasMonacoErrorRef.current = hasMonacoError;\n\n const renderErrorOutline = !!error || hasMonacoError;\n const theme = useMantineTheme();\n const {colorScheme} = useMantineColorScheme();\n\n useEffect(() => {\n if (monacoLoader === 'local') {\n loadLocalMonaco();\n } else {\n setLoaded(true);\n }\n }, []);\n\n const handleValidate = (markers: monacoEditor.IMarker[]) => {\n setHasMonacoError(markers.some((marker) => marker.severity === MarkerSeverity.Error));\n };\n\n const _label = label ? (\n <Input.Label required={required} {...labelProps}>\n {label}\n </Input.Label>\n ) : null;\n\n const _description = description ? (\n <Input.Description {...descriptionProps}>{description}</Input.Description>\n ) : null;\n\n const _error = error ? (\n <Input.Error mt=\"xs\" {...errorProps}>\n {error}\n </Input.Error>\n ) : (\n <Space h=\"xs\" />\n );\n\n const _header =\n _label || _description ? (\n <Box>\n {_label}\n {_description}\n </Box>\n ) : null;\n\n const _buttons = (\n <Group justify=\"right\" gap={0}>\n <Search handleSearch={handleSearch} />\n <CopyToClipboard value={_value} onCopy={() => onCopy?.()} />\n </Group>\n );\n let editorTheme = colorScheme === 'light' ? 'light' : 'vs-dark';\n if (disabled) {\n editorTheme += '-disabled';\n }\n\n const _editor = loaded ? (\n <Box\n p=\"md\"\n pl=\"xs\"\n className={cx(\n CodeEditorClasses.editor,\n {[CodeEditorClasses.valid]: !renderErrorOutline},\n {[CodeEditorClasses.error]: renderErrorOutline},\n {[CodeEditorClasses.disabled]: disabled},\n )}\n data-testid=\"editor-wrapper\"\n >\n <Editor\n onValidate={handleValidate}\n defaultLanguage={language}\n theme={editorTheme}\n options={{\n minimap: {enabled: false},\n wordWrap: 'on',\n scrollBeyondLastLine: false,\n formatOnPaste: true,\n fontSize: px(theme.fontSizes.xs) as number,\n readOnly: disabled,\n tabSize,\n }}\n value={_value}\n onChange={handleChange}\n onMount={(editor, monaco) => {\n editorRef.current = editor;\n registerLanguages(monaco);\n registerThemes(monaco);\n editor.onDidFocusEditorText(() => onFocus?.());\n editor.onDidBlurEditorText(async () => {\n // monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that\n setTimeout(async () => {\n if (!hasMonacoErrorRef.current) {\n await editor.getAction('editor.action.formatDocument').run();\n }\n }, 550);\n });\n }}\n />\n </Box>\n ) : (\n <Center className={CodeEditorClasses.editor}>\n <Loader />\n </Center>\n );\n\n return (\n <Stack justify=\"flex-start\" gap={0} h={Math.max(parentHeight, minHeight)} mah={maxHeight} ref={ref} {...others}>\n {_header}\n {_buttons}\n {_editor}\n {_error}\n </Stack>\n );\n};\n"],"names":["Box","Center","Group","Input","Loader","Space","Stack","px","useMantineColorScheme","useMantineTheme","useProps","useUncontrolled","Editor","loader","MarkerSeverity","useEffect","useRef","useState","cx","useParentHeight","CopyToClipboard","CodeEditorClasses","XML","Search","defaultProps","language","monacoLoader","defaultValue","minHeight","CodeEditor","props","onChange","onCopy","onSearch","onFocus","value","label","required","labelProps","error","errorProps","description","descriptionProps","maxHeight","disabled","options","tabSize","others","loaded","setLoaded","_value","handleChange","finalValue","parentHeight","ref","editorRef","loadLocalMonaco","monacoInstance","config","monaco","registerLanguages","register","registerThemes","editor","defineTheme","base","inherit","rules","colors","theme","gray","navy","handleSearch","current","focus","trigger","hasMonacoError","setHasMonacoError","hasMonacoErrorRef","renderErrorOutline","colorScheme","handleValidate","markers","some","marker","severity","Error","_label","Label","_description","Description","_error","mt","h","_header","_buttons","justify","gap","editorTheme","_editor","p","pl","className","valid","data-testid","onValidate","defaultLanguage","minimap","enabled","wordWrap","scrollBeyondLastLine","formatOnPaste","fontSize","fontSizes","xs","readOnly","onMount","onDidFocusEditorText","onDidBlurEditorText","setTimeout","getAction","run","Math","max","mah"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/code-editor/CodeEditor.tsx"],"sourcesContent":["import {\n Box,\n Center,\n Group,\n Input,\n InputWrapperProps,\n Loader,\n Space,\n Stack,\n StackProps,\n px,\n useMantineColorScheme,\n useMantineTheme,\n useProps,\n} from '@mantine/core';\nimport {useUncontrolled} from '@mantine/hooks';\nimport Editor, {Monaco, loader} from '@monaco-editor/react';\nimport {MarkerSeverity, editor as monacoEditor} from 'monaco-editor';\nimport {FunctionComponent, useEffect, useRef, useState} from 'react';\n\nimport cx from 'clsx';\nimport {useParentHeight} from '../../hooks';\nimport {CopyToClipboard} from '../copyToClipboard';\nimport CodeEditorClasses from './CodeEditor.module.css';\nimport {XML} from './languages/xml';\nimport {Search} from './search';\ninterface CodeEditorProps\n extends Omit<\n InputWrapperProps,\n 'inputContainer' | 'inputWrapperOrder' | 'classNames' | 'styles' | 'vars' | 'onChange'\n >,\n Omit<StackProps, 'onChange'> {\n /**\n * The language syntax of the editor\n *\n * @default 'plaintext'\n */\n language?: 'plaintext' | 'json' | 'markdown' | 'python' | 'xml' | (string & unknown);\n /** Default value for uncontrolled input */\n defaultValue?: string;\n /** Value for controlled input */\n value?: string;\n /** onChange value for controlled input */\n onChange?(value: string): void;\n /** Called whenever the search icon is clicked */\n onSearch?(): void;\n /** Called whenever the copy icon is clicked */\n onCopy?(): void;\n /** Called whenever the code editor gets the focus */\n onFocus?(): void;\n /** Ref object that provides access to the editor's functionality */\n editorHandle?: React.MutableRefObject<monacoEditor.IStandaloneCodeEditor | null>;\n /**\n * The minimal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height is too short, it will use this value as minimum.\n *\n * @default 300\n */\n minHeight?: number;\n /**\n * The maximal height of the CodeEditor (label and description included)\n *\n * By default the CodeEditor is adjusted to fill its parent height.\n * In the case where the parent height would be too high for your liking, you can use this prop to set a maximum.\n */\n maxHeight?: number;\n disabled?: boolean;\n /**\n * Defines how the monaco editor files will be loaded.\n * Note that using `'local'` requires [some additional configuration](https://github.com/suren-atoyan/monaco-react#use-monaco-editor-as-an-npm-package).\n *\n * @default 'local'\n */\n monacoLoader?: 'cdn' | 'local';\n /**\n * Options to pass to the monaco editor.\n * Currently only supporting [`tabSize`](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html#tabSize).\n *\n */\n options?: Pick<monacoEditor.IStandaloneEditorConstructionOptions, 'tabSize'>;\n}\n\nconst defaultProps: Partial<CodeEditorProps> = {\n language: 'plaintext',\n monacoLoader: 'local',\n defaultValue: '',\n minHeight: 300,\n};\n\nexport const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {\n const {\n language,\n defaultValue,\n onChange,\n onCopy,\n onSearch,\n onFocus,\n value,\n label,\n required,\n labelProps,\n error,\n errorProps,\n description,\n descriptionProps,\n minHeight,\n maxHeight,\n disabled,\n monacoLoader,\n options: {tabSize} = {tabSize: 2},\n editorHandle,\n ...others\n } = useProps('CodeEditor', defaultProps, props);\n const [loaded, setLoaded] = useState(false);\n const [_value, handleChange] = useUncontrolled<string>({\n value,\n defaultValue,\n onChange,\n finalValue: '',\n });\n const [parentHeight, ref] = useParentHeight();\n const editorRef = useRef(null);\n\n const loadLocalMonaco = async () => {\n const monacoInstance = await import('monaco-editor');\n loader.config({monaco: monacoInstance});\n setLoaded(true);\n };\n\n const registerLanguages = (monaco: Monaco) => {\n if (monaco && language === 'xml') {\n XML.register(monaco);\n }\n };\n\n const registerThemes = (monaco: Monaco) => {\n monaco.editor.defineTheme('light-disabled', {\n base: 'vs',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.gray[2],\n },\n });\n monaco.editor.defineTheme('vs-dark-disabled', {\n base: 'vs-dark',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': theme.colors.navy[7],\n },\n });\n };\n\n const handleSearch = () => {\n if (editorRef.current) {\n editorRef.current.focus();\n editorRef.current.trigger('editor', 'actions.find', '');\n onSearch?.();\n }\n };\n\n const [hasMonacoError, setHasMonacoError] = useState(false);\n const hasMonacoErrorRef = useRef(false);\n\n hasMonacoErrorRef.current = hasMonacoError;\n\n const renderErrorOutline = !!error || hasMonacoError;\n const theme = useMantineTheme();\n const {colorScheme} = useMantineColorScheme();\n\n useEffect(() => {\n if (monacoLoader === 'local') {\n loadLocalMonaco();\n } else {\n setLoaded(true);\n }\n }, []);\n\n const handleValidate = (markers: monacoEditor.IMarker[]) => {\n setHasMonacoError(markers.some((marker) => marker.severity === MarkerSeverity.Error));\n };\n\n const _label = label ? (\n <Input.Label required={required} {...labelProps}>\n {label}\n </Input.Label>\n ) : null;\n\n const _description = description ? (\n <Input.Description {...descriptionProps}>{description}</Input.Description>\n ) : null;\n\n const _error = error ? (\n <Input.Error mt=\"xs\" {...errorProps}>\n {error}\n </Input.Error>\n ) : (\n <Space h=\"xs\" />\n );\n\n const _header =\n _label || _description ? (\n <Box>\n {_label}\n {_description}\n </Box>\n ) : null;\n\n const _buttons = (\n <Group justify=\"right\" gap={0}>\n <Search handleSearch={handleSearch} />\n <CopyToClipboard value={_value} onCopy={() => onCopy?.()} />\n </Group>\n );\n let editorTheme = colorScheme === 'light' ? 'light' : 'vs-dark';\n if (disabled) {\n editorTheme += '-disabled';\n }\n\n const _editor = loaded ? (\n <Box\n p=\"md\"\n pl=\"xs\"\n className={cx(\n CodeEditorClasses.editor,\n {[CodeEditorClasses.valid]: !renderErrorOutline},\n {[CodeEditorClasses.error]: renderErrorOutline},\n {[CodeEditorClasses.disabled]: disabled},\n )}\n data-testid=\"editor-wrapper\"\n >\n <Editor\n onValidate={handleValidate}\n defaultLanguage={language}\n theme={editorTheme}\n options={{\n minimap: {enabled: false},\n wordWrap: 'on',\n scrollBeyondLastLine: false,\n formatOnPaste: true,\n fontSize: px(theme.fontSizes.xs) as number,\n readOnly: disabled,\n tabSize,\n }}\n value={_value}\n onChange={handleChange}\n onMount={(editor, monaco) => {\n editorRef.current = editor;\n if (editorHandle) {\n editorHandle.current = editor;\n }\n registerLanguages(monaco);\n registerThemes(monaco);\n editor.onDidFocusEditorText(() => onFocus?.());\n editor.onDidBlurEditorText(async () => {\n // monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that\n setTimeout(async () => {\n if (!hasMonacoErrorRef.current) {\n await editor?.getAction('editor.action.formatDocument')?.run();\n }\n }, 550);\n });\n }}\n />\n </Box>\n ) : (\n <Center className={CodeEditorClasses.editor}>\n <Loader />\n </Center>\n );\n\n return (\n <Stack justify=\"flex-start\" gap={0} h={Math.max(parentHeight, minHeight)} mah={maxHeight} ref={ref} {...others}>\n {_header}\n {_buttons}\n {_editor}\n {_error}\n </Stack>\n );\n};\n"],"names":["Box","Center","Group","Input","Loader","Space","Stack","px","useMantineColorScheme","useMantineTheme","useProps","useUncontrolled","Editor","loader","MarkerSeverity","useEffect","useRef","useState","cx","useParentHeight","CopyToClipboard","CodeEditorClasses","XML","Search","defaultProps","language","monacoLoader","defaultValue","minHeight","CodeEditor","props","onChange","onCopy","onSearch","onFocus","value","label","required","labelProps","error","errorProps","description","descriptionProps","maxHeight","disabled","options","tabSize","editorHandle","others","loaded","setLoaded","_value","handleChange","finalValue","parentHeight","ref","editorRef","loadLocalMonaco","monacoInstance","config","monaco","registerLanguages","register","registerThemes","editor","defineTheme","base","inherit","rules","colors","theme","gray","navy","handleSearch","current","focus","trigger","hasMonacoError","setHasMonacoError","hasMonacoErrorRef","renderErrorOutline","colorScheme","handleValidate","markers","some","marker","severity","Error","_label","Label","_description","Description","_error","mt","h","_header","_buttons","justify","gap","editorTheme","_editor","p","pl","className","valid","data-testid","onValidate","defaultLanguage","minimap","enabled","wordWrap","scrollBeyondLastLine","formatOnPaste","fontSize","fontSizes","xs","readOnly","onMount","onDidFocusEditorText","onDidBlurEditorText","setTimeout","getAction","run","Math","max","mah"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coveord/plasma-mantine",
|
|
3
|
-
"version": "55.
|
|
3
|
+
"version": "55.8.0",
|
|
4
4
|
"description": "A Plasma flavoured Mantine theme",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"plasma",
|
|
@@ -42,28 +42,29 @@
|
|
|
42
42
|
"lodash.debounce": "4.0.8",
|
|
43
43
|
"lodash.defaultsdeep": "4.6.1",
|
|
44
44
|
"monaco-editor": "0.52.2",
|
|
45
|
-
"@coveord/plasma-
|
|
46
|
-
"@coveord/plasma-
|
|
45
|
+
"@coveord/plasma-react-icons": "55.8.0",
|
|
46
|
+
"@coveord/plasma-tokens": "55.8.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@mantine/carousel": "7.17.
|
|
50
|
-
"@mantine/code-highlight": "7.17.
|
|
51
|
-
"@mantine/core": "7.17.
|
|
52
|
-
"@mantine/dates": "7.17.
|
|
53
|
-
"@mantine/form": "7.17.
|
|
54
|
-
"@mantine/hooks": "7.17.
|
|
55
|
-
"@mantine/modals": "7.17.
|
|
56
|
-
"@mantine/notifications": "7.17.
|
|
49
|
+
"@mantine/carousel": "7.17.3",
|
|
50
|
+
"@mantine/code-highlight": "7.17.3",
|
|
51
|
+
"@mantine/core": "7.17.3",
|
|
52
|
+
"@mantine/dates": "7.17.3",
|
|
53
|
+
"@mantine/form": "7.17.3",
|
|
54
|
+
"@mantine/hooks": "7.17.3",
|
|
55
|
+
"@mantine/modals": "7.17.3",
|
|
56
|
+
"@mantine/notifications": "7.17.3",
|
|
57
57
|
"@swc/cli": "0.6.0",
|
|
58
|
-
"@swc/core": "1.11.
|
|
58
|
+
"@swc/core": "1.11.16",
|
|
59
59
|
"@testing-library/dom": "10.4.0",
|
|
60
60
|
"@testing-library/jest-dom": "6.6.3",
|
|
61
61
|
"@testing-library/react": "16.2.0",
|
|
62
62
|
"@testing-library/user-event": "14.6.1",
|
|
63
63
|
"@types/lodash.debounce": "4.0.9",
|
|
64
64
|
"@types/lodash.defaultsdeep": "4.6.9",
|
|
65
|
-
"@types/react": "18.3.
|
|
65
|
+
"@types/react": "18.3.20",
|
|
66
66
|
"@types/react-dom": "18.3.5",
|
|
67
|
+
"cross-env": "7.0.3",
|
|
67
68
|
"embla-carousel-react": "7.1.0",
|
|
68
69
|
"identity-obj-proxy": "3.0.0",
|
|
69
70
|
"jsdom": "26.0.0",
|
|
@@ -74,10 +75,10 @@
|
|
|
74
75
|
"react": "18.3.1",
|
|
75
76
|
"react-dom": "18.3.1",
|
|
76
77
|
"rimraf": "6.0.1",
|
|
77
|
-
"sass": "1.
|
|
78
|
+
"sass": "1.86.1",
|
|
78
79
|
"tslib": "2.8.1",
|
|
79
80
|
"typescript": "5.8.2",
|
|
80
|
-
"vitest": "3.
|
|
81
|
+
"vitest": "3.1.1"
|
|
81
82
|
},
|
|
82
83
|
"peerDependencies": {
|
|
83
84
|
"@mantine/carousel": "^7.6.1",
|
|
@@ -120,7 +121,7 @@
|
|
|
120
121
|
"clean": "rimraf dist",
|
|
121
122
|
"lintfix": "../../node_modules/.bin/prettier --write \"**/*.{scss,ts,tsx,js,jsx,json,md,yml,html}\" && ../../node_modules/.bin/eslint \"**/*.{ts,tsx}\" --fix",
|
|
122
123
|
"start": "node ../../scripts/start",
|
|
123
|
-
"test": "TZ=UTC vitest run",
|
|
124
|
-
"test:watch": "TZ=UTC vitest"
|
|
124
|
+
"test": "cross-env TZ=UTC vitest run",
|
|
125
|
+
"test:watch": "cross-env TZ=UTC vitest"
|
|
125
126
|
}
|
|
126
127
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from '@mantine/core';
|
|
16
16
|
import {useUncontrolled} from '@mantine/hooks';
|
|
17
17
|
import Editor, {Monaco, loader} from '@monaco-editor/react';
|
|
18
|
-
import {editor as monacoEditor
|
|
18
|
+
import {MarkerSeverity, editor as monacoEditor} from 'monaco-editor';
|
|
19
19
|
import {FunctionComponent, useEffect, useRef, useState} from 'react';
|
|
20
20
|
|
|
21
21
|
import cx from 'clsx';
|
|
@@ -48,6 +48,8 @@ interface CodeEditorProps
|
|
|
48
48
|
onCopy?(): void;
|
|
49
49
|
/** Called whenever the code editor gets the focus */
|
|
50
50
|
onFocus?(): void;
|
|
51
|
+
/** Ref object that provides access to the editor's functionality */
|
|
52
|
+
editorHandle?: React.MutableRefObject<monacoEditor.IStandaloneCodeEditor | null>;
|
|
51
53
|
/**
|
|
52
54
|
* The minimal height of the CodeEditor (label and description included)
|
|
53
55
|
*
|
|
@@ -108,6 +110,7 @@ export const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {
|
|
|
108
110
|
disabled,
|
|
109
111
|
monacoLoader,
|
|
110
112
|
options: {tabSize} = {tabSize: 2},
|
|
113
|
+
editorHandle,
|
|
111
114
|
...others
|
|
112
115
|
} = useProps('CodeEditor', defaultProps, props);
|
|
113
116
|
const [loaded, setLoaded] = useState(false);
|
|
@@ -119,6 +122,7 @@ export const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {
|
|
|
119
122
|
});
|
|
120
123
|
const [parentHeight, ref] = useParentHeight();
|
|
121
124
|
const editorRef = useRef(null);
|
|
125
|
+
|
|
122
126
|
const loadLocalMonaco = async () => {
|
|
123
127
|
const monacoInstance = await import('monaco-editor');
|
|
124
128
|
loader.config({monaco: monacoInstance});
|
|
@@ -245,6 +249,9 @@ export const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {
|
|
|
245
249
|
onChange={handleChange}
|
|
246
250
|
onMount={(editor, monaco) => {
|
|
247
251
|
editorRef.current = editor;
|
|
252
|
+
if (editorHandle) {
|
|
253
|
+
editorHandle.current = editor;
|
|
254
|
+
}
|
|
248
255
|
registerLanguages(monaco);
|
|
249
256
|
registerThemes(monaco);
|
|
250
257
|
editor.onDidFocusEditorText(() => onFocus?.());
|
|
@@ -252,7 +259,7 @@ export const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {
|
|
|
252
259
|
// monaco editor has a timeout of 500ms populating errors, we want to ensure that checking errors happen after that
|
|
253
260
|
setTimeout(async () => {
|
|
254
261
|
if (!hasMonacoErrorRef.current) {
|
|
255
|
-
await editor
|
|
262
|
+
await editor?.getAction('editor.action.formatDocument')?.run();
|
|
256
263
|
}
|
|
257
264
|
}, 550);
|
|
258
265
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {useForm} from '@mantine/form';
|
|
2
2
|
import {loader} from '@monaco-editor/react';
|
|
3
3
|
import {render, screen, userEvent, waitForElementToBeRemoved} from '@test-utils';
|
|
4
|
+
import type {editor} from 'monaco-editor';
|
|
5
|
+
import {useRef} from 'react';
|
|
4
6
|
import {CodeEditor} from '../CodeEditor';
|
|
5
7
|
import {XML} from '../languages/xml';
|
|
6
8
|
|
|
@@ -88,4 +90,18 @@ describe('CodeEditor', () => {
|
|
|
88
90
|
|
|
89
91
|
expect(onSearchSpy).toHaveBeenCalledTimes(1);
|
|
90
92
|
});
|
|
93
|
+
|
|
94
|
+
it('defines editorHandle on mount', async () => {
|
|
95
|
+
let editorHandle: React.MutableRefObject<editor.IStandaloneCodeEditor> = null;
|
|
96
|
+
const EditorWrapper = () => {
|
|
97
|
+
editorHandle = useRef<editor.IStandaloneCodeEditor | null>(null);
|
|
98
|
+
return <CodeEditor editorHandle={editorHandle} />;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
render(<EditorWrapper />);
|
|
102
|
+
|
|
103
|
+
await waitForElementToBeRemoved(screen.queryByRole('presentation'));
|
|
104
|
+
|
|
105
|
+
expect(editorHandle.current).not.toBeNull();
|
|
106
|
+
});
|
|
91
107
|
});
|