@snack-uikit/code-editor 0.4.7 → 0.5.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/CHANGELOG.md +11 -0
- package/README.md +15 -0
- package/dist/cjs/components/CodeEditor.d.ts +3 -3
- package/dist/cjs/components/CodeEditor.js +12 -6
- package/dist/cjs/components/constants.d.ts +6 -0
- package/dist/cjs/components/constants.js +8 -2
- package/dist/cjs/components/hooks.d.ts +7 -0
- package/dist/cjs/components/hooks.js +61 -3
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/index.js +2 -1
- package/dist/cjs/components/types.d.ts +25 -0
- package/dist/cjs/components/types.js +5 -0
- package/dist/cjs/components/utils.d.ts +3 -0
- package/dist/cjs/components/utils.js +8 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +7 -1
- package/dist/esm/components/CodeEditor.d.ts +3 -3
- package/dist/esm/components/CodeEditor.js +6 -5
- package/dist/esm/components/constants.d.ts +6 -0
- package/dist/esm/components/constants.js +6 -0
- package/dist/esm/components/hooks.d.ts +7 -0
- package/dist/esm/components/hooks.js +57 -2
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/components/types.d.ts +25 -0
- package/dist/esm/components/types.js +1 -0
- package/dist/esm/components/utils.d.ts +3 -0
- package/dist/esm/components/utils.js +2 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/package.json +4 -3
- package/src/components/CodeEditor.tsx +14 -4
- package/src/components/constants.ts +8 -0
- package/src/components/hooks.ts +71 -2
- package/src/components/index.ts +1 -0
- package/src/components/types.ts +33 -0
- package/src/components/utils.ts +7 -0
- package/src/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 0.5.0 (2025-02-07)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **PDS-1445:** support json schema for yaml, json languages ([a709fe5](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/commits/a709fe5e061917c5017de1bd1b6f01c15f4b3002))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## 0.4.7 (2025-01-23)
|
|
7
18
|
|
|
8
19
|
### Only dependencies have been changed
|
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
### Props
|
|
13
13
|
| name | type | default value | description |
|
|
14
14
|
|------|------|---------------|-------------|
|
|
15
|
+
| jsonSchema* | `JsonSchema` | - | Схема для валидации |
|
|
15
16
|
| themeName | `string` | - | Название текущей темы. Значение не важно, важно что смена значения запускает пересчет стилей. |
|
|
16
17
|
| hasBackground | `boolean` | true | Включение/отключение псевдобекграунда |
|
|
17
18
|
| defaultValue | `string` | - | Default value of the current model |
|
|
@@ -38,3 +39,17 @@
|
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
[//]: DOCUMENTATION_SECTION_END
|
|
42
|
+
|
|
43
|
+
### Поддержка YAML
|
|
44
|
+
Для обеспечения полноценной работы YAML Monaco Editor необходимо подключить `yaml.worker`. Это можно сделать следующими способами: с использованием [`window.MonacoEnvironment`](https://www.npmjs.com/package/monaco-yaml#usage) или с помощью плагина [`MonacoWebpackPlugin`](https://www.npmjs.com/package/monaco-yaml#using-monaco-webpack-loader-plugin) . Подробнее с `monaco-yaml` можно ознакомиться [тут]((https://www.npmjs.com/package/monaco-yaml))
|
|
45
|
+
|
|
46
|
+
### Как редактор загружает worker?
|
|
47
|
+
Плагин создает новые точки входа каждого build-in воркера и для каждого дабавленного отдельно. Плагин создат глобальную переменную, используя которую редкатор будет загружать нужный воркер на основе текущего `language`.
|
|
48
|
+
|
|
49
|
+
Чтобы управлять конфигурацией загрузчика Monaco Editor, добавьте
|
|
50
|
+
```typescript
|
|
51
|
+
import * as monaco from 'monaco-editor';
|
|
52
|
+
import { loader } from '@snack-uikit/code-editor';
|
|
53
|
+
loader.config({ monaco });
|
|
54
|
+
```
|
|
55
|
+
Это позволяет динамически настраивать пути и другие параметры при инициализации редактора.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EditorProps } from '@monaco-editor/react';
|
|
2
1
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
2
|
+
import { EditorBaseProps, EditorWithJsonSchemaProps } from './types';
|
|
3
3
|
export type CodeEditorProps = WithSupportProps<{
|
|
4
4
|
/**
|
|
5
5
|
* Название текущей темы. Значение не важно, важно что смена значения запускает пересчет стилей.
|
|
@@ -9,5 +9,5 @@ export type CodeEditorProps = WithSupportProps<{
|
|
|
9
9
|
* Включение/отключение псевдобекграунда
|
|
10
10
|
*/
|
|
11
11
|
hasBackground?: boolean;
|
|
12
|
-
}> &
|
|
13
|
-
export declare function CodeEditor({ themeName, className, theme, options, loading, hasBackground, onMount, ...props }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
}> & (EditorBaseProps | EditorWithJsonSchemaProps);
|
|
13
|
+
export declare function CodeEditor({ themeName, className, theme, options, loading, hasBackground, onMount, language, ...props }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -36,11 +36,16 @@ function CodeEditor(_a) {
|
|
|
36
36
|
options,
|
|
37
37
|
loading,
|
|
38
38
|
hasBackground = true,
|
|
39
|
-
onMount
|
|
39
|
+
onMount,
|
|
40
|
+
language
|
|
40
41
|
} = _a,
|
|
41
|
-
props = __rest(_a, ["themeName", "className", "theme", "options", "loading", "hasBackground", "onMount"]);
|
|
42
|
+
props = __rest(_a, ["themeName", "className", "theme", "options", "loading", "hasBackground", "onMount", "language"]);
|
|
42
43
|
const monaco = (0, react_1.useMonaco)();
|
|
43
44
|
const [wrapperElement, setWrapperElement] = (0, react_2.useState)(null);
|
|
45
|
+
const {
|
|
46
|
+
jsonSchemaProps,
|
|
47
|
+
jsonSchemaOptions
|
|
48
|
+
} = (0, hooks_1.useApplyJsonSchema)(language, 'jsonSchema' in props ? props.jsonSchema : undefined);
|
|
44
49
|
const onEditorMount = (0, react_2.useCallback)((editor, monaco) => {
|
|
45
50
|
var _a;
|
|
46
51
|
monaco && (0, utils_1.isBrowser)() && ((_a = document === null || document === void 0 ? void 0 : document.fonts) === null || _a === void 0 ? void 0 : _a.ready.finally(monaco.editor.remeasureFonts));
|
|
@@ -101,23 +106,24 @@ function CodeEditor(_a) {
|
|
|
101
106
|
monaco === null || monaco === void 0 ? void 0 : monaco.editor.defineTheme('snack', Object.assign(Object.assign({}, themeDataWithoutBase), {
|
|
102
107
|
base: 'vs'
|
|
103
108
|
}));
|
|
104
|
-
const mergedOptions = (0, react_2.useMemo)(() => Object.assign(Object.assign(Object.assign({}, constants_1.CODE_EDITOR_OPTIONS), (themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono) ? {
|
|
109
|
+
const mergedOptions = (0, react_2.useMemo)(() => Object.assign(Object.assign(Object.assign(Object.assign({}, constants_1.CODE_EDITOR_OPTIONS), jsonSchemaOptions), (themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono) ? {
|
|
105
110
|
fontSize: Number.parseFloat(themeValues.mono.body.s['font-size']),
|
|
106
111
|
fontWeight: themeValues.mono.body.s['font-weight'],
|
|
107
112
|
fontFamily: themeValues.mono.body.s['font-family']
|
|
108
|
-
} : constants_1.DEFAULT_THEME_OPTIONS.mono.s), options), [options, themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono]);
|
|
113
|
+
} : constants_1.DEFAULT_THEME_OPTIONS.mono.s), options), [options, themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono, jsonSchemaOptions]);
|
|
109
114
|
return (0, jsx_runtime_1.jsx)("div", Object.assign({
|
|
110
115
|
className: className
|
|
111
116
|
}, (0, utils_1.extractSupportProps)(props), {
|
|
112
117
|
ref: setWrapperElement,
|
|
113
|
-
children: (0, jsx_runtime_1.jsx)(react_1.Editor, Object.assign({}, props, {
|
|
118
|
+
children: (0, jsx_runtime_1.jsx)(react_1.Editor, Object.assign({}, props, jsonSchemaProps, {
|
|
114
119
|
theme: theme !== null && theme !== void 0 ? theme : dark ? 'snackDark' : 'snack',
|
|
115
120
|
className: (0, classnames_1.default)({
|
|
116
121
|
[styles_module_scss_1.default.editor]: hasBackground
|
|
117
122
|
}),
|
|
118
123
|
loading: loading !== null && loading !== void 0 ? loading : (0, jsx_runtime_1.jsx)(loaders_1.Spinner, {}),
|
|
119
124
|
options: mergedOptions,
|
|
120
|
-
onMount: onEditorMount
|
|
125
|
+
onMount: onEditorMount,
|
|
126
|
+
language: language
|
|
121
127
|
}))
|
|
122
128
|
}));
|
|
123
129
|
}
|
|
@@ -99,3 +99,9 @@ export declare const CODE_EDITOR_OPTIONS: {
|
|
|
99
99
|
indentation: boolean;
|
|
100
100
|
};
|
|
101
101
|
};
|
|
102
|
+
export declare const YAML_CODE_EDITOR_OPTIONS: {
|
|
103
|
+
quickSuggestions: {
|
|
104
|
+
strings: boolean;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
export declare const DEFAULT_SCHEMA_URI = "schema://editor-schema";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.CODE_EDITOR_OPTIONS = exports.THEME_VARS = exports.DEFAULT_THEME_OPTIONS = exports.DEFAULT_THEME_VALUES = void 0;
|
|
6
|
+
exports.DEFAULT_SCHEMA_URI = exports.YAML_CODE_EDITOR_OPTIONS = exports.CODE_EDITOR_OPTIONS = exports.THEME_VARS = exports.DEFAULT_THEME_OPTIONS = exports.DEFAULT_THEME_VALUES = void 0;
|
|
7
7
|
exports.DEFAULT_THEME_VALUES = {
|
|
8
8
|
semanticTokenColors: {
|
|
9
9
|
enumMember: {
|
|
@@ -113,4 +113,10 @@ exports.CODE_EDITOR_OPTIONS = {
|
|
|
113
113
|
guides: {
|
|
114
114
|
indentation: false
|
|
115
115
|
}
|
|
116
|
-
};
|
|
116
|
+
};
|
|
117
|
+
exports.YAML_CODE_EDITOR_OPTIONS = {
|
|
118
|
+
quickSuggestions: {
|
|
119
|
+
strings: true
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
exports.DEFAULT_SCHEMA_URI = 'schema://editor-schema';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JsonSchema } from './types';
|
|
1
2
|
type UseCalculatedThemeValuesProps = {
|
|
2
3
|
stylesOriginNode: HTMLDivElement | null;
|
|
3
4
|
themeName?: string;
|
|
@@ -41,4 +42,10 @@ export declare function useCalculatedThemeValues({ stylesOriginNode, themeName }
|
|
|
41
42
|
};
|
|
42
43
|
};
|
|
43
44
|
} | undefined;
|
|
45
|
+
export declare function useApplyJsonSchema(language?: string, jsonSchema?: JsonSchema): {
|
|
46
|
+
jsonSchemaProps: {
|
|
47
|
+
path: string | undefined;
|
|
48
|
+
};
|
|
49
|
+
jsonSchemaOptions: import("monaco-editor").editor.IStandaloneEditorConstructionOptions | undefined;
|
|
50
|
+
};
|
|
44
51
|
export {};
|
|
@@ -4,9 +4,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.useCalculatedThemeValues = useCalculatedThemeValues;
|
|
7
|
-
|
|
7
|
+
exports.useApplyJsonSchema = useApplyJsonSchema;
|
|
8
|
+
const react_1 = require("@monaco-editor/react");
|
|
9
|
+
const monaco_yaml_1 = require("monaco-yaml");
|
|
10
|
+
const react_2 = require("react");
|
|
8
11
|
const utils_1 = require("@snack-uikit/utils");
|
|
9
12
|
const constants_1 = require("./constants");
|
|
13
|
+
const utils_2 = require("./utils");
|
|
10
14
|
function getThemeVars(styles) {
|
|
11
15
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
16
|
return function mapComputedTree(tree) {
|
|
@@ -25,16 +29,70 @@ function useCalculatedThemeValues(_ref) {
|
|
|
25
29
|
stylesOriginNode,
|
|
26
30
|
themeName
|
|
27
31
|
} = _ref;
|
|
28
|
-
const [values, setValues] = (0,
|
|
32
|
+
const [values, setValues] = (0, react_2.useState)(undefined);
|
|
29
33
|
const {
|
|
30
34
|
themeClassName
|
|
31
35
|
} = (0, utils_1.useThemeContext)();
|
|
32
36
|
const trigger = themeName !== null && themeName !== void 0 ? themeName : themeClassName;
|
|
33
|
-
(0,
|
|
37
|
+
(0, react_2.useEffect)(() => {
|
|
34
38
|
if (stylesOriginNode) {
|
|
35
39
|
const styles = getComputedStyle(stylesOriginNode);
|
|
36
40
|
setValues(getThemeVars(styles)(constants_1.THEME_VARS));
|
|
37
41
|
}
|
|
38
42
|
}, [stylesOriginNode, trigger]);
|
|
39
43
|
return values;
|
|
44
|
+
}
|
|
45
|
+
function useApplyJsonSchema(language, jsonSchema) {
|
|
46
|
+
const monaco = (0, react_1.useMonaco)();
|
|
47
|
+
const [jsonSchemaOptions, setJsonSchemaOptions] = (0, react_2.useState)({});
|
|
48
|
+
const modelPath = jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.fileMatch;
|
|
49
|
+
const preparedJsonSchema = (0, react_2.useMemo)(() => (0, utils_2.getJsonSchema)(jsonSchema), [jsonSchema]);
|
|
50
|
+
const configureYamlLanguage = (0, react_2.useCallback)(() => {
|
|
51
|
+
if (!monaco || !preparedJsonSchema) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const model = (0, monaco_yaml_1.configureMonacoYaml)(monaco, {
|
|
55
|
+
enableSchemaRequest: true,
|
|
56
|
+
schemas: [preparedJsonSchema]
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
options: constants_1.YAML_CODE_EDITOR_OPTIONS,
|
|
60
|
+
dispose: model.dispose
|
|
61
|
+
};
|
|
62
|
+
}, [monaco, preparedJsonSchema]);
|
|
63
|
+
const configureJsonLanguage = (0, react_2.useCallback)(() => {
|
|
64
|
+
if (!monaco || !preparedJsonSchema) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
68
|
+
validate: true,
|
|
69
|
+
schemas: [preparedJsonSchema]
|
|
70
|
+
});
|
|
71
|
+
}, [monaco, preparedJsonSchema]);
|
|
72
|
+
const configureJsonSchema = (0, react_2.useCallback)(() => {
|
|
73
|
+
switch (language) {
|
|
74
|
+
case 'yaml':
|
|
75
|
+
return configureYamlLanguage();
|
|
76
|
+
case 'json':
|
|
77
|
+
return configureJsonLanguage();
|
|
78
|
+
default:
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}, [language, configureYamlLanguage, configureJsonLanguage]);
|
|
82
|
+
(0, react_2.useEffect)(() => {
|
|
83
|
+
var _a;
|
|
84
|
+
const jsonSchemaSettings = configureJsonSchema();
|
|
85
|
+
setJsonSchemaOptions((_a = jsonSchemaSettings === null || jsonSchemaSettings === void 0 ? void 0 : jsonSchemaSettings.options) !== null && _a !== void 0 ? _a : {});
|
|
86
|
+
return () => {
|
|
87
|
+
var _a;
|
|
88
|
+
setJsonSchemaOptions({});
|
|
89
|
+
(_a = jsonSchemaSettings === null || jsonSchemaSettings === void 0 ? void 0 : jsonSchemaSettings.dispose) === null || _a === void 0 ? void 0 : _a.call(jsonSchemaSettings);
|
|
90
|
+
};
|
|
91
|
+
}, [configureJsonSchema]);
|
|
92
|
+
return (0, react_2.useMemo)(() => ({
|
|
93
|
+
jsonSchemaProps: {
|
|
94
|
+
path: modelPath
|
|
95
|
+
},
|
|
96
|
+
jsonSchemaOptions
|
|
97
|
+
}), [jsonSchemaOptions, modelPath]);
|
|
40
98
|
}
|
|
@@ -22,4 +22,5 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", {
|
|
23
23
|
value: true
|
|
24
24
|
});
|
|
25
|
-
__exportStar(require("./CodeEditor"), exports);
|
|
25
|
+
__exportStar(require("./CodeEditor"), exports);
|
|
26
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EditorProps as MonacoEditorProps } from '@monaco-editor/react';
|
|
2
|
+
import { JSONSchema } from 'monaco-yaml';
|
|
3
|
+
export type EditorBaseProps = MonacoEditorProps;
|
|
4
|
+
export type SupportedSchemaLanguage = 'json' | 'yaml';
|
|
5
|
+
export type JsonSchema = {
|
|
6
|
+
uri?: string;
|
|
7
|
+
schema: JSONSchema;
|
|
8
|
+
fileMatch: string;
|
|
9
|
+
};
|
|
10
|
+
export type WithJsonSchema = {
|
|
11
|
+
/**
|
|
12
|
+
* Схема для валидации
|
|
13
|
+
*/
|
|
14
|
+
jsonSchema: JsonSchema;
|
|
15
|
+
path?: never;
|
|
16
|
+
};
|
|
17
|
+
type WithoutJsonSchema = Pick<MonacoEditorProps, 'path'>;
|
|
18
|
+
export type EditorWithJsonSchemaProps = Omit<EditorBaseProps, 'language' | 'path'> & {
|
|
19
|
+
language: SupportedSchemaLanguage;
|
|
20
|
+
} & (WithJsonSchema | WithoutJsonSchema);
|
|
21
|
+
export type ConfigureJsonSchemaReturn = {
|
|
22
|
+
options?: MonacoEditorProps['options'];
|
|
23
|
+
dispose?: () => void;
|
|
24
|
+
} | undefined;
|
|
25
|
+
export {};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { SchemasSettings } from 'monaco-yaml';
|
|
2
|
+
import { JsonSchema } from './types';
|
|
1
3
|
export declare function rgb2hsl(HTMLcolor: string): number[];
|
|
2
4
|
export declare function isDark(color: string): boolean;
|
|
3
5
|
export declare function initLoaderConfig(): void;
|
|
6
|
+
export declare const getJsonSchema: (jsonSchema?: JsonSchema) => SchemasSettings | undefined;
|
|
@@ -8,11 +8,13 @@ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", {
|
|
9
9
|
value: true
|
|
10
10
|
});
|
|
11
|
+
exports.getJsonSchema = void 0;
|
|
11
12
|
exports.rgb2hsl = rgb2hsl;
|
|
12
13
|
exports.isDark = isDark;
|
|
13
14
|
exports.initLoaderConfig = initLoaderConfig;
|
|
14
15
|
const react_1 = require("@monaco-editor/react");
|
|
15
16
|
const chroma_js_1 = __importDefault(require("chroma-js"));
|
|
17
|
+
const constants_1 = require("./constants");
|
|
16
18
|
function rgb2hsl(HTMLcolor) {
|
|
17
19
|
const [r, g, b] = chroma_js_1.default.valid(HTMLcolor) ? (0, chroma_js_1.default)(HTMLcolor).rgb().map(c => c / 255) : [0, 0, 0];
|
|
18
20
|
const max = Math.max(r, g, b),
|
|
@@ -53,4 +55,9 @@ function initLoaderConfig() {
|
|
|
53
55
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
54
56
|
// @ts-ignore
|
|
55
57
|
window['__snack-code-editor-loader-config__'] && react_1.loader.config(window['__snack-code-editor-loader-config__']);
|
|
56
|
-
}
|
|
58
|
+
}
|
|
59
|
+
const getJsonSchema = jsonSchema => jsonSchema && Object.assign(Object.assign({}, jsonSchema), {
|
|
60
|
+
uri: (jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.uri) || constants_1.DEFAULT_SCHEMA_URI,
|
|
61
|
+
fileMatch: [jsonSchema.fileMatch]
|
|
62
|
+
});
|
|
63
|
+
exports.getJsonSchema = getJsonSchema;
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Monaco loader defines the way how monaco will be loaded.
|
|
3
3
|
@see https://github.com/suren-atoyan/monaco-react/tree/master?tab=readme-ov-file#loader-config
|
|
4
4
|
*/
|
|
5
|
-
export { loader } from '@monaco-editor/react';
|
|
5
|
+
export { loader, useMonaco } from '@monaco-editor/react';
|
|
6
6
|
export * from './components';
|
package/dist/cjs/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", {
|
|
23
23
|
value: true
|
|
24
24
|
});
|
|
25
|
-
exports.loader = void 0;
|
|
25
|
+
exports.useMonaco = exports.loader = void 0;
|
|
26
26
|
/**
|
|
27
27
|
Monaco loader defines the way how monaco will be loaded.
|
|
28
28
|
@see https://github.com/suren-atoyan/monaco-react/tree/master?tab=readme-ov-file#loader-config
|
|
@@ -34,4 +34,10 @@ Object.defineProperty(exports, "loader", {
|
|
|
34
34
|
return react_1.loader;
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
+
Object.defineProperty(exports, "useMonaco", {
|
|
38
|
+
enumerable: true,
|
|
39
|
+
get: function () {
|
|
40
|
+
return react_1.useMonaco;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
37
43
|
__exportStar(require("./components"), exports);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EditorProps } from '@monaco-editor/react';
|
|
2
1
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
2
|
+
import { EditorBaseProps, EditorWithJsonSchemaProps } from './types';
|
|
3
3
|
export type CodeEditorProps = WithSupportProps<{
|
|
4
4
|
/**
|
|
5
5
|
* Название текущей темы. Значение не важно, важно что смена значения запускает пересчет стилей.
|
|
@@ -9,5 +9,5 @@ export type CodeEditorProps = WithSupportProps<{
|
|
|
9
9
|
* Включение/отключение псевдобекграунда
|
|
10
10
|
*/
|
|
11
11
|
hasBackground?: boolean;
|
|
12
|
-
}> &
|
|
13
|
-
export declare function CodeEditor({ themeName, className, theme, options, loading, hasBackground, onMount, ...props }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
}> & (EditorBaseProps | EditorWithJsonSchemaProps);
|
|
13
|
+
export declare function CodeEditor({ themeName, className, theme, options, loading, hasBackground, onMount, language, ...props }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -16,14 +16,15 @@ import { useCallback, useMemo, useState } from 'react';
|
|
|
16
16
|
import { Spinner } from '@snack-uikit/loaders';
|
|
17
17
|
import { extractSupportProps, isBrowser } from '@snack-uikit/utils';
|
|
18
18
|
import { CODE_EDITOR_OPTIONS, DEFAULT_THEME_OPTIONS, DEFAULT_THEME_VALUES } from './constants';
|
|
19
|
-
import { useCalculatedThemeValues } from './hooks';
|
|
19
|
+
import { useApplyJsonSchema, useCalculatedThemeValues } from './hooks';
|
|
20
20
|
import styles from './styles.module.css';
|
|
21
21
|
import { initLoaderConfig, isDark } from './utils';
|
|
22
22
|
initLoaderConfig();
|
|
23
23
|
export function CodeEditor(_a) {
|
|
24
|
-
var { themeName, className, theme, options, loading, hasBackground = true, onMount } = _a, props = __rest(_a, ["themeName", "className", "theme", "options", "loading", "hasBackground", "onMount"]);
|
|
24
|
+
var { themeName, className, theme, options, loading, hasBackground = true, onMount, language } = _a, props = __rest(_a, ["themeName", "className", "theme", "options", "loading", "hasBackground", "onMount", "language"]);
|
|
25
25
|
const monaco = useMonaco();
|
|
26
26
|
const [wrapperElement, setWrapperElement] = useState(null);
|
|
27
|
+
const { jsonSchemaProps, jsonSchemaOptions } = useApplyJsonSchema(language, 'jsonSchema' in props ? props.jsonSchema : undefined);
|
|
27
28
|
const onEditorMount = useCallback((editor, monaco) => {
|
|
28
29
|
var _a;
|
|
29
30
|
monaco && isBrowser() && ((_a = document === null || document === void 0 ? void 0 : document.fonts) === null || _a === void 0 ? void 0 : _a.ready.finally(monaco.editor.remeasureFonts));
|
|
@@ -79,12 +80,12 @@ export function CodeEditor(_a) {
|
|
|
79
80
|
const dark = useMemo(() => { var _a; return isDark((_a = themeValues === null || themeValues === void 0 ? void 0 : themeValues.sys.available.complementary) !== null && _a !== void 0 ? _a : ''); }, [themeValues === null || themeValues === void 0 ? void 0 : themeValues.sys.available.complementary]);
|
|
80
81
|
monaco === null || monaco === void 0 ? void 0 : monaco.editor.defineTheme('snackDark', Object.assign(Object.assign({}, themeDataWithoutBase), { base: 'vs-dark' }));
|
|
81
82
|
monaco === null || monaco === void 0 ? void 0 : monaco.editor.defineTheme('snack', Object.assign(Object.assign({}, themeDataWithoutBase), { base: 'vs' }));
|
|
82
|
-
const mergedOptions = useMemo(() => (Object.assign(Object.assign(Object.assign({}, CODE_EDITOR_OPTIONS), ((themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono)
|
|
83
|
+
const mergedOptions = useMemo(() => (Object.assign(Object.assign(Object.assign(Object.assign({}, CODE_EDITOR_OPTIONS), jsonSchemaOptions), ((themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono)
|
|
83
84
|
? {
|
|
84
85
|
fontSize: Number.parseFloat(themeValues.mono.body.s['font-size']),
|
|
85
86
|
fontWeight: themeValues.mono.body.s['font-weight'],
|
|
86
87
|
fontFamily: themeValues.mono.body.s['font-family'],
|
|
87
88
|
}
|
|
88
|
-
: DEFAULT_THEME_OPTIONS.mono.s)), options)), [options, themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono]);
|
|
89
|
-
return (_jsx("div", Object.assign({ className: className }, extractSupportProps(props), { ref: setWrapperElement, children: _jsx(Editor, Object.assign({}, props, { theme: theme !== null && theme !== void 0 ? theme : (dark ? 'snackDark' : 'snack'), className: cn({ [styles.editor]: hasBackground }), loading: loading !== null && loading !== void 0 ? loading : _jsx(Spinner, {}), options: mergedOptions, onMount: onEditorMount })) })));
|
|
89
|
+
: DEFAULT_THEME_OPTIONS.mono.s)), options)), [options, themeValues === null || themeValues === void 0 ? void 0 : themeValues.mono, jsonSchemaOptions]);
|
|
90
|
+
return (_jsx("div", Object.assign({ className: className }, extractSupportProps(props), { ref: setWrapperElement, children: _jsx(Editor, Object.assign({}, props, jsonSchemaProps, { theme: theme !== null && theme !== void 0 ? theme : (dark ? 'snackDark' : 'snack'), className: cn({ [styles.editor]: hasBackground }), loading: loading !== null && loading !== void 0 ? loading : _jsx(Spinner, {}), options: mergedOptions, onMount: onEditorMount, language: language })) })));
|
|
90
91
|
}
|
|
@@ -99,3 +99,9 @@ export declare const CODE_EDITOR_OPTIONS: {
|
|
|
99
99
|
indentation: boolean;
|
|
100
100
|
};
|
|
101
101
|
};
|
|
102
|
+
export declare const YAML_CODE_EDITOR_OPTIONS: {
|
|
103
|
+
quickSuggestions: {
|
|
104
|
+
strings: boolean;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
export declare const DEFAULT_SCHEMA_URI = "schema://editor-schema";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JsonSchema } from './types';
|
|
1
2
|
type UseCalculatedThemeValuesProps = {
|
|
2
3
|
stylesOriginNode: HTMLDivElement | null;
|
|
3
4
|
themeName?: string;
|
|
@@ -41,4 +42,10 @@ export declare function useCalculatedThemeValues({ stylesOriginNode, themeName }
|
|
|
41
42
|
};
|
|
42
43
|
};
|
|
43
44
|
} | undefined;
|
|
45
|
+
export declare function useApplyJsonSchema(language?: string, jsonSchema?: JsonSchema): {
|
|
46
|
+
jsonSchemaProps: {
|
|
47
|
+
path: string | undefined;
|
|
48
|
+
};
|
|
49
|
+
jsonSchemaOptions: import("monaco-editor").editor.IStandaloneEditorConstructionOptions | undefined;
|
|
50
|
+
};
|
|
44
51
|
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMonaco } from '@monaco-editor/react';
|
|
2
|
+
import { configureMonacoYaml } from 'monaco-yaml';
|
|
3
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
4
|
import { useThemeContext } from '@snack-uikit/utils';
|
|
3
|
-
import { THEME_VARS } from './constants';
|
|
5
|
+
import { THEME_VARS, YAML_CODE_EDITOR_OPTIONS } from './constants';
|
|
6
|
+
import { getJsonSchema } from './utils';
|
|
4
7
|
function getThemeVars(styles) {
|
|
5
8
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
9
|
return function mapComputedTree(tree) {
|
|
@@ -26,3 +29,55 @@ export function useCalculatedThemeValues({ stylesOriginNode, themeName }) {
|
|
|
26
29
|
}, [stylesOriginNode, trigger]);
|
|
27
30
|
return values;
|
|
28
31
|
}
|
|
32
|
+
export function useApplyJsonSchema(language, jsonSchema) {
|
|
33
|
+
const monaco = useMonaco();
|
|
34
|
+
const [jsonSchemaOptions, setJsonSchemaOptions] = useState({});
|
|
35
|
+
const modelPath = jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.fileMatch;
|
|
36
|
+
const preparedJsonSchema = useMemo(() => getJsonSchema(jsonSchema), [jsonSchema]);
|
|
37
|
+
const configureYamlLanguage = useCallback(() => {
|
|
38
|
+
if (!monaco || !preparedJsonSchema) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const model = configureMonacoYaml(monaco, {
|
|
42
|
+
enableSchemaRequest: true,
|
|
43
|
+
schemas: [preparedJsonSchema],
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
options: YAML_CODE_EDITOR_OPTIONS,
|
|
47
|
+
dispose: model.dispose,
|
|
48
|
+
};
|
|
49
|
+
}, [monaco, preparedJsonSchema]);
|
|
50
|
+
const configureJsonLanguage = useCallback(() => {
|
|
51
|
+
if (!monaco || !preparedJsonSchema) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
55
|
+
validate: true,
|
|
56
|
+
schemas: [preparedJsonSchema],
|
|
57
|
+
});
|
|
58
|
+
}, [monaco, preparedJsonSchema]);
|
|
59
|
+
const configureJsonSchema = useCallback(() => {
|
|
60
|
+
switch (language) {
|
|
61
|
+
case 'yaml':
|
|
62
|
+
return configureYamlLanguage();
|
|
63
|
+
case 'json':
|
|
64
|
+
return configureJsonLanguage();
|
|
65
|
+
default:
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}, [language, configureYamlLanguage, configureJsonLanguage]);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
var _a;
|
|
71
|
+
const jsonSchemaSettings = configureJsonSchema();
|
|
72
|
+
setJsonSchemaOptions((_a = jsonSchemaSettings === null || jsonSchemaSettings === void 0 ? void 0 : jsonSchemaSettings.options) !== null && _a !== void 0 ? _a : {});
|
|
73
|
+
return () => {
|
|
74
|
+
var _a;
|
|
75
|
+
setJsonSchemaOptions({});
|
|
76
|
+
(_a = jsonSchemaSettings === null || jsonSchemaSettings === void 0 ? void 0 : jsonSchemaSettings.dispose) === null || _a === void 0 ? void 0 : _a.call(jsonSchemaSettings);
|
|
77
|
+
};
|
|
78
|
+
}, [configureJsonSchema]);
|
|
79
|
+
return useMemo(() => ({
|
|
80
|
+
jsonSchemaProps: { path: modelPath },
|
|
81
|
+
jsonSchemaOptions,
|
|
82
|
+
}), [jsonSchemaOptions, modelPath]);
|
|
83
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EditorProps as MonacoEditorProps } from '@monaco-editor/react';
|
|
2
|
+
import { JSONSchema } from 'monaco-yaml';
|
|
3
|
+
export type EditorBaseProps = MonacoEditorProps;
|
|
4
|
+
export type SupportedSchemaLanguage = 'json' | 'yaml';
|
|
5
|
+
export type JsonSchema = {
|
|
6
|
+
uri?: string;
|
|
7
|
+
schema: JSONSchema;
|
|
8
|
+
fileMatch: string;
|
|
9
|
+
};
|
|
10
|
+
export type WithJsonSchema = {
|
|
11
|
+
/**
|
|
12
|
+
* Схема для валидации
|
|
13
|
+
*/
|
|
14
|
+
jsonSchema: JsonSchema;
|
|
15
|
+
path?: never;
|
|
16
|
+
};
|
|
17
|
+
type WithoutJsonSchema = Pick<MonacoEditorProps, 'path'>;
|
|
18
|
+
export type EditorWithJsonSchemaProps = Omit<EditorBaseProps, 'language' | 'path'> & {
|
|
19
|
+
language: SupportedSchemaLanguage;
|
|
20
|
+
} & (WithJsonSchema | WithoutJsonSchema);
|
|
21
|
+
export type ConfigureJsonSchemaReturn = {
|
|
22
|
+
options?: MonacoEditorProps['options'];
|
|
23
|
+
dispose?: () => void;
|
|
24
|
+
} | undefined;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { SchemasSettings } from 'monaco-yaml';
|
|
2
|
+
import { JsonSchema } from './types';
|
|
1
3
|
export declare function rgb2hsl(HTMLcolor: string): number[];
|
|
2
4
|
export declare function isDark(color: string): boolean;
|
|
3
5
|
export declare function initLoaderConfig(): void;
|
|
6
|
+
export declare const getJsonSchema: (jsonSchema?: JsonSchema) => SchemasSettings | undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { loader } from '@monaco-editor/react';
|
|
2
2
|
import chroma from 'chroma-js';
|
|
3
|
+
import { DEFAULT_SCHEMA_URI } from './constants';
|
|
3
4
|
export function rgb2hsl(HTMLcolor) {
|
|
4
5
|
const [r, g, b] = chroma.valid(HTMLcolor)
|
|
5
6
|
? chroma(HTMLcolor)
|
|
@@ -45,3 +46,4 @@ export function initLoaderConfig() {
|
|
|
45
46
|
// @ts-ignore
|
|
46
47
|
window['__snack-code-editor-loader-config__'] && loader.config(window['__snack-code-editor-loader-config__']);
|
|
47
48
|
}
|
|
49
|
+
export const getJsonSchema = (jsonSchema) => jsonSchema && Object.assign(Object.assign({}, jsonSchema), { uri: (jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.uri) || DEFAULT_SCHEMA_URI, fileMatch: [jsonSchema.fileMatch] });
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Monaco loader defines the way how monaco will be loaded.
|
|
3
3
|
@see https://github.com/suren-atoyan/monaco-react/tree/master?tab=readme-ov-file#loader-config
|
|
4
4
|
*/
|
|
5
|
-
export { loader } from '@monaco-editor/react';
|
|
5
|
+
export { loader, useMonaco } from '@monaco-editor/react';
|
|
6
6
|
export * from './components';
|
package/dist/esm/index.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Monaco loader defines the way how monaco will be loaded.
|
|
3
3
|
@see https://github.com/suren-atoyan/monaco-react/tree/master?tab=readme-ov-file#loader-config
|
|
4
4
|
*/
|
|
5
|
-
export { loader } from '@monaco-editor/react';
|
|
5
|
+
export { loader, useMonaco } from '@monaco-editor/react';
|
|
6
6
|
export * from './components';
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.5.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -40,10 +40,11 @@
|
|
|
40
40
|
"@snack-uikit/loaders": "0.9.1",
|
|
41
41
|
"@snack-uikit/utils": "3.7.0",
|
|
42
42
|
"chroma-js": "3.1.2",
|
|
43
|
-
"classnames": "2.5.1"
|
|
43
|
+
"classnames": "2.5.1",
|
|
44
|
+
"monaco-yaml": "5.2.3"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@types/chroma-js": "2.4.4"
|
|
47
48
|
},
|
|
48
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "7bf9ee3ad1d793050e82a48a95d317bc97510da0"
|
|
49
50
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Editor,
|
|
1
|
+
import { Editor, OnMount, useMonaco } from '@monaco-editor/react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import { useCallback, useMemo, useState } from 'react';
|
|
4
4
|
|
|
@@ -6,8 +6,9 @@ import { Spinner } from '@snack-uikit/loaders';
|
|
|
6
6
|
import { extractSupportProps, isBrowser, WithSupportProps } from '@snack-uikit/utils';
|
|
7
7
|
|
|
8
8
|
import { CODE_EDITOR_OPTIONS, DEFAULT_THEME_OPTIONS, DEFAULT_THEME_VALUES } from './constants';
|
|
9
|
-
import { useCalculatedThemeValues } from './hooks';
|
|
9
|
+
import { useApplyJsonSchema, useCalculatedThemeValues } from './hooks';
|
|
10
10
|
import styles from './styles.module.scss';
|
|
11
|
+
import { EditorBaseProps, EditorWithJsonSchemaProps } from './types';
|
|
11
12
|
import { initLoaderConfig, isDark } from './utils';
|
|
12
13
|
|
|
13
14
|
initLoaderConfig();
|
|
@@ -22,7 +23,7 @@ export type CodeEditorProps = WithSupportProps<{
|
|
|
22
23
|
*/
|
|
23
24
|
hasBackground?: boolean;
|
|
24
25
|
}> &
|
|
25
|
-
|
|
26
|
+
(EditorBaseProps | EditorWithJsonSchemaProps);
|
|
26
27
|
|
|
27
28
|
export function CodeEditor({
|
|
28
29
|
themeName,
|
|
@@ -32,11 +33,17 @@ export function CodeEditor({
|
|
|
32
33
|
loading,
|
|
33
34
|
hasBackground = true,
|
|
34
35
|
onMount,
|
|
36
|
+
language,
|
|
35
37
|
...props
|
|
36
38
|
}: CodeEditorProps) {
|
|
37
39
|
const monaco = useMonaco();
|
|
38
40
|
const [wrapperElement, setWrapperElement] = useState<HTMLDivElement | null>(null);
|
|
39
41
|
|
|
42
|
+
const { jsonSchemaProps, jsonSchemaOptions } = useApplyJsonSchema(
|
|
43
|
+
language,
|
|
44
|
+
'jsonSchema' in props ? props.jsonSchema : undefined,
|
|
45
|
+
);
|
|
46
|
+
|
|
40
47
|
const onEditorMount = useCallback<OnMount>(
|
|
41
48
|
(editor, monaco) => {
|
|
42
49
|
monaco && isBrowser() && document?.fonts?.ready.finally(monaco.editor.remeasureFonts);
|
|
@@ -111,6 +118,7 @@ export function CodeEditor({
|
|
|
111
118
|
const mergedOptions = useMemo(
|
|
112
119
|
() => ({
|
|
113
120
|
...CODE_EDITOR_OPTIONS,
|
|
121
|
+
...jsonSchemaOptions,
|
|
114
122
|
...(themeValues?.mono
|
|
115
123
|
? {
|
|
116
124
|
fontSize: Number.parseFloat(themeValues.mono.body.s['font-size']),
|
|
@@ -120,18 +128,20 @@ export function CodeEditor({
|
|
|
120
128
|
: DEFAULT_THEME_OPTIONS.mono.s),
|
|
121
129
|
...options,
|
|
122
130
|
}),
|
|
123
|
-
[options, themeValues?.mono],
|
|
131
|
+
[options, themeValues?.mono, jsonSchemaOptions],
|
|
124
132
|
);
|
|
125
133
|
|
|
126
134
|
return (
|
|
127
135
|
<div className={className} {...extractSupportProps(props)} ref={setWrapperElement}>
|
|
128
136
|
<Editor
|
|
129
137
|
{...props}
|
|
138
|
+
{...jsonSchemaProps}
|
|
130
139
|
theme={theme ?? (dark ? 'snackDark' : 'snack')}
|
|
131
140
|
className={cn({ [styles.editor]: hasBackground })}
|
|
132
141
|
loading={loading ?? <Spinner />}
|
|
133
142
|
options={mergedOptions}
|
|
134
143
|
onMount={onEditorMount}
|
|
144
|
+
language={language}
|
|
135
145
|
/>
|
|
136
146
|
</div>
|
|
137
147
|
);
|
package/src/components/hooks.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EditorProps as MonacoEditorProps, useMonaco } from '@monaco-editor/react';
|
|
2
|
+
import { configureMonacoYaml, SchemasSettings } from 'monaco-yaml';
|
|
3
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
4
|
|
|
3
5
|
import { useThemeContext } from '@snack-uikit/utils';
|
|
4
6
|
|
|
5
|
-
import { THEME_VARS } from './constants';
|
|
7
|
+
import { THEME_VARS, YAML_CODE_EDITOR_OPTIONS } from './constants';
|
|
8
|
+
import { ConfigureJsonSchemaReturn, JsonSchema } from './types';
|
|
9
|
+
import { getJsonSchema } from './utils';
|
|
6
10
|
|
|
7
11
|
function getThemeVars(styles: CSSStyleDeclaration) {
|
|
8
12
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -42,3 +46,68 @@ export function useCalculatedThemeValues({ stylesOriginNode, themeName }: UseCal
|
|
|
42
46
|
|
|
43
47
|
return values;
|
|
44
48
|
}
|
|
49
|
+
|
|
50
|
+
export function useApplyJsonSchema(language?: string, jsonSchema?: JsonSchema) {
|
|
51
|
+
const monaco = useMonaco();
|
|
52
|
+
|
|
53
|
+
const [jsonSchemaOptions, setJsonSchemaOptions] = useState<MonacoEditorProps['options']>({});
|
|
54
|
+
const modelPath = jsonSchema?.fileMatch;
|
|
55
|
+
|
|
56
|
+
const preparedJsonSchema: SchemasSettings | undefined = useMemo(() => getJsonSchema(jsonSchema), [jsonSchema]);
|
|
57
|
+
|
|
58
|
+
const configureYamlLanguage = useCallback((): ConfigureJsonSchemaReturn => {
|
|
59
|
+
if (!monaco || !preparedJsonSchema) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const model = configureMonacoYaml(monaco, {
|
|
64
|
+
enableSchemaRequest: true,
|
|
65
|
+
schemas: [preparedJsonSchema],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
options: YAML_CODE_EDITOR_OPTIONS,
|
|
70
|
+
dispose: model.dispose,
|
|
71
|
+
};
|
|
72
|
+
}, [monaco, preparedJsonSchema]);
|
|
73
|
+
|
|
74
|
+
const configureJsonLanguage = useCallback((): ConfigureJsonSchemaReturn => {
|
|
75
|
+
if (!monaco || !preparedJsonSchema) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
80
|
+
validate: true,
|
|
81
|
+
schemas: [preparedJsonSchema],
|
|
82
|
+
});
|
|
83
|
+
}, [monaco, preparedJsonSchema]);
|
|
84
|
+
|
|
85
|
+
const configureJsonSchema = useCallback(() => {
|
|
86
|
+
switch (language) {
|
|
87
|
+
case 'yaml':
|
|
88
|
+
return configureYamlLanguage();
|
|
89
|
+
case 'json':
|
|
90
|
+
return configureJsonLanguage();
|
|
91
|
+
default:
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}, [language, configureYamlLanguage, configureJsonLanguage]);
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const jsonSchemaSettings = configureJsonSchema();
|
|
98
|
+
setJsonSchemaOptions(jsonSchemaSettings?.options ?? {});
|
|
99
|
+
|
|
100
|
+
return () => {
|
|
101
|
+
setJsonSchemaOptions({});
|
|
102
|
+
jsonSchemaSettings?.dispose?.();
|
|
103
|
+
};
|
|
104
|
+
}, [configureJsonSchema]);
|
|
105
|
+
|
|
106
|
+
return useMemo(
|
|
107
|
+
() => ({
|
|
108
|
+
jsonSchemaProps: { path: modelPath } satisfies MonacoEditorProps,
|
|
109
|
+
jsonSchemaOptions,
|
|
110
|
+
}),
|
|
111
|
+
[jsonSchemaOptions, modelPath],
|
|
112
|
+
);
|
|
113
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { EditorProps as MonacoEditorProps } from '@monaco-editor/react';
|
|
2
|
+
import { JSONSchema } from 'monaco-yaml';
|
|
3
|
+
|
|
4
|
+
export type EditorBaseProps = MonacoEditorProps;
|
|
5
|
+
|
|
6
|
+
export type SupportedSchemaLanguage = 'json' | 'yaml';
|
|
7
|
+
|
|
8
|
+
export type JsonSchema = {
|
|
9
|
+
uri?: string;
|
|
10
|
+
schema: JSONSchema;
|
|
11
|
+
fileMatch: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type WithJsonSchema = {
|
|
15
|
+
/**
|
|
16
|
+
* Схема для валидации
|
|
17
|
+
*/
|
|
18
|
+
jsonSchema: JsonSchema;
|
|
19
|
+
path?: never;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type WithoutJsonSchema = Pick<MonacoEditorProps, 'path'>;
|
|
23
|
+
|
|
24
|
+
export type EditorWithJsonSchemaProps = Omit<EditorBaseProps, 'language' | 'path'> & {
|
|
25
|
+
language: SupportedSchemaLanguage;
|
|
26
|
+
} & (WithJsonSchema | WithoutJsonSchema);
|
|
27
|
+
|
|
28
|
+
export type ConfigureJsonSchemaReturn =
|
|
29
|
+
| {
|
|
30
|
+
options?: MonacoEditorProps['options'];
|
|
31
|
+
dispose?: () => void;
|
|
32
|
+
}
|
|
33
|
+
| undefined;
|
package/src/components/utils.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { loader } from '@monaco-editor/react';
|
|
2
2
|
import chroma from 'chroma-js';
|
|
3
|
+
import { SchemasSettings } from 'monaco-yaml';
|
|
4
|
+
|
|
5
|
+
import { DEFAULT_SCHEMA_URI } from './constants';
|
|
6
|
+
import { JsonSchema } from './types';
|
|
3
7
|
|
|
4
8
|
export function rgb2hsl(HTMLcolor: string) {
|
|
5
9
|
const [r, g, b] = chroma.valid(HTMLcolor)
|
|
@@ -60,3 +64,6 @@ export function initLoaderConfig() {
|
|
|
60
64
|
// @ts-ignore
|
|
61
65
|
window['__snack-code-editor-loader-config__'] && loader.config(window['__snack-code-editor-loader-config__']);
|
|
62
66
|
}
|
|
67
|
+
|
|
68
|
+
export const getJsonSchema = (jsonSchema?: JsonSchema): SchemasSettings | undefined =>
|
|
69
|
+
jsonSchema && { ...jsonSchema, uri: jsonSchema?.uri || DEFAULT_SCHEMA_URI, fileMatch: [jsonSchema.fileMatch] };
|
package/src/index.ts
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Monaco loader defines the way how monaco will be loaded.
|
|
3
3
|
@see https://github.com/suren-atoyan/monaco-react/tree/master?tab=readme-ov-file#loader-config
|
|
4
4
|
*/
|
|
5
|
-
export { loader } from '@monaco-editor/react';
|
|
5
|
+
export { loader, useMonaco } from '@monaco-editor/react';
|
|
6
6
|
export * from './components';
|