@react-fabric/monaco 1.0.0-beta.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/LICENSE +21 -0
- package/README.md +10 -0
- package/dist/cjs/components/CodeEditor.js +146 -0
- package/dist/cjs/components/CodeEditor.module.css +1 -0
- package/dist/cjs/index.js +7 -0
- package/dist/esm/components/CodeEditor.js +146 -0
- package/dist/esm/components/CodeEditor.module.css +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/types/components/CodeEditor.d.ts +18 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +55 -0
- package/src/components/CodeEditor.module.css +92 -0
- package/src/components/CodeEditor.tsx +205 -0
- package/src/index.ts +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 React Fabric, Adarsh Pastakia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
|
|
4
|
+
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
|
|
5
|
+
var _toArray = require('@babel/runtime/helpers/toArray');
|
|
6
|
+
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
|
7
|
+
var core = require('@react-fabric/core');
|
|
8
|
+
var utilities = require('@react-fabric/utilities');
|
|
9
|
+
var classNames = require('classnames');
|
|
10
|
+
var react = require('react');
|
|
11
|
+
var MonacoEditor = require('react-monaco-editor');
|
|
12
|
+
var CodeEditor_module = require('./CodeEditor.module.css');
|
|
13
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
14
|
+
|
|
15
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
16
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
17
|
+
var CodeEditor = function CodeEditor(_ref) {
|
|
18
|
+
var ref = _ref.ref,
|
|
19
|
+
value = _ref.value,
|
|
20
|
+
schema = _ref.schema,
|
|
21
|
+
required = _ref.required,
|
|
22
|
+
readOnly = _ref.readOnly,
|
|
23
|
+
minimal = _ref.minimal,
|
|
24
|
+
onChange = _ref.onChange,
|
|
25
|
+
_ref$language = _ref.language,
|
|
26
|
+
language = _ref$language === void 0 ? "json" : _ref$language;
|
|
27
|
+
var _useState = react.useState(),
|
|
28
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
29
|
+
editorRef = _useState2[0],
|
|
30
|
+
setEditorRef = _useState2[1];
|
|
31
|
+
var _useState3 = react.useState(),
|
|
32
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
33
|
+
monacoRef = _useState4[0],
|
|
34
|
+
setMonacoRef = _useState4[1];
|
|
35
|
+
var isDark = core.useIsDark();
|
|
36
|
+
|
|
37
|
+
/** ***************** watch theme change *******************/
|
|
38
|
+
var _useState5 = react.useState(""),
|
|
39
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
40
|
+
theme = _useState6[0],
|
|
41
|
+
setTheme = _useState6[1];
|
|
42
|
+
react.useLayoutEffect(function () {
|
|
43
|
+
editorRef && setTheme(isDark ? "vs-dark" : "light");
|
|
44
|
+
}, [isDark, editorRef]);
|
|
45
|
+
|
|
46
|
+
/** ***************** watch editor container resize *******************/
|
|
47
|
+
var resizeHandler = react.useCallback(function (size) {
|
|
48
|
+
return editorRef === null || editorRef === void 0 ? void 0 : editorRef.layout(size);
|
|
49
|
+
}, [editorRef]);
|
|
50
|
+
var containerRef = core.useResizeObserver(resizeHandler);
|
|
51
|
+
|
|
52
|
+
/** ***************** defer value and pass to editor as defaultValue *******************/
|
|
53
|
+
var deferredValue = react.useDeferredValue(value);
|
|
54
|
+
var codeValue = react.useMemo(function () {
|
|
55
|
+
return utilities.isString(deferredValue) ? deferredValue : JSON.stringify(deferredValue, null, 4);
|
|
56
|
+
}, [deferredValue]);
|
|
57
|
+
var handleChange = core.useDebounce(function (value) {
|
|
58
|
+
var model = editorRef === null || editorRef === void 0 ? void 0 : editorRef.getModel();
|
|
59
|
+
if (model) {
|
|
60
|
+
var markers = monacoRef === null || monacoRef === void 0 ? void 0 : monacoRef.editor.getModelMarkers({
|
|
61
|
+
owner: model.getLanguageId()
|
|
62
|
+
});
|
|
63
|
+
(markers === null || markers === void 0 ? void 0 : markers.filter(function (m) {
|
|
64
|
+
return m.severity > 7;
|
|
65
|
+
}).length) === 0 && (onChange === null || onChange === void 0 ? void 0 : onChange(value));
|
|
66
|
+
}
|
|
67
|
+
}, [onChange, editorRef], 1000);
|
|
68
|
+
react.useImperativeHandle(ref, function () {
|
|
69
|
+
return {
|
|
70
|
+
getValue: function getValue() {
|
|
71
|
+
return editorRef === null || editorRef === void 0 ? void 0 : editorRef.getValue();
|
|
72
|
+
},
|
|
73
|
+
validate: function validate() {
|
|
74
|
+
var model = editorRef === null || editorRef === void 0 ? void 0 : editorRef.getModel();
|
|
75
|
+
if (model) {
|
|
76
|
+
var markers = monacoRef === null || monacoRef === void 0 ? void 0 : monacoRef.editor.getModelMarkers({
|
|
77
|
+
owner: model.getLanguageId()
|
|
78
|
+
});
|
|
79
|
+
return (markers === null || markers === void 0 ? void 0 : markers.filter(function (m) {
|
|
80
|
+
return m.severity > 8;
|
|
81
|
+
}).length) === 0;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
var val = editorRef === null || editorRef === void 0 ? void 0 : editorRef.getValue();
|
|
85
|
+
if (language === "json") val = JSON.parse(val);
|
|
86
|
+
return required ? !utilities.isEmpty(val) : true;
|
|
87
|
+
} catch (_unused) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}, [required, language]);
|
|
93
|
+
var schemaUri = react.useCallback(function (monaco) {
|
|
94
|
+
if (schema) {
|
|
95
|
+
var _schema = _toArray(schema),
|
|
96
|
+
main = _schema[0],
|
|
97
|
+
rest = _schema.slice(1);
|
|
98
|
+
// configure the JSON language support with schemas and schema associations
|
|
99
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
100
|
+
validate: true,
|
|
101
|
+
allowComments: false,
|
|
102
|
+
schemas: [_objectSpread({
|
|
103
|
+
fileMatch: ["*"]
|
|
104
|
+
}, main)].concat(_toConsumableArray(rest))
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}, [schema]);
|
|
108
|
+
var resetSchema = react.useCallback(function (_, monaco) {
|
|
109
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
110
|
+
validate: true,
|
|
111
|
+
allowComments: false,
|
|
112
|
+
schemas: []
|
|
113
|
+
});
|
|
114
|
+
}, []);
|
|
115
|
+
return /*#__PURE__*/jsxRuntime.jsx(core.Section, {
|
|
116
|
+
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
117
|
+
ref: containerRef,
|
|
118
|
+
className: classNames(CodeEditor_module.codeEditor, "area-content"),
|
|
119
|
+
children: /*#__PURE__*/jsxRuntime.jsx(MonacoEditor, {
|
|
120
|
+
editorDidMount: function editorDidMount(e, m) {
|
|
121
|
+
return [!!e && setEditorRef(e), !!m && setMonacoRef(m)];
|
|
122
|
+
},
|
|
123
|
+
editorWillMount: schemaUri,
|
|
124
|
+
editorWillUnmount: resetSchema,
|
|
125
|
+
value: codeValue,
|
|
126
|
+
language: language,
|
|
127
|
+
onChange: handleChange,
|
|
128
|
+
theme: theme,
|
|
129
|
+
className: CodeEditor_module.editor,
|
|
130
|
+
options: {
|
|
131
|
+
readOnly: readOnly,
|
|
132
|
+
minimap: {
|
|
133
|
+
enabled: !minimal
|
|
134
|
+
},
|
|
135
|
+
scrollBeyondLastLine: false,
|
|
136
|
+
folding: !minimal,
|
|
137
|
+
lineNumbers: minimal ? "off" : undefined,
|
|
138
|
+
wordWrap: "on",
|
|
139
|
+
fontFamily: 'Menlo, Monaco, "Courier New", monospace'
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
exports.CodeEditor = CodeEditor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer util{.codeEditor{border:solid transparent;border-width:1px 1px 2px;direction:ltr;overflow:hidden;&:has(:global(.monaco-editor.focused)){border-color:theme(borderColor.primary.500)}.editor{&>:global(.monaco-editor){--vscode-menu-background:theme(colors.tint.50)!important;--vscode-menu-border:theme(borderColor.base)!important;--vscode-focusBorder:transparent!important;--vscode-menu-selectionBackground:color(from var(--primary) srgb r g b/80%)!important;--vscode-editor-background:var(--fabric-bg)!important;--vscode-editor-foreground:var(--fabric-text)!important;--vscode-breadcrumb-background:var(--fabric-bg)!important;--vscode-editorGutter-background:color(from theme(colors.tint.50) srgb r g g/50%)!important;--vscode-minimapSlider-background:color(from var(--tint) srgb r g b/20%)!important;--vscode-minimapSlider-hoverBackground:color(from var(--tint) srgb r g b/25%)!important;--vscode-minimapSlider-activeBackground:color(from var(--tint) srgb r g b/30%)!important;--vscode-input-border:var(--primary)!important;--vscode-editorStickyScroll-background:var(--fabric-bg)!important;--vscode-editorMarkerNavigation-background:var(--fabric-bg)!important;--vscode-editor-wordHighlightTextBackground:color(from theme(colors.accent.700) srgb r g b/20%)!important}& :global(.minimap-decorations-layer){background-color:color(from theme(colors.tint.50) srgb r g g/50%)!important}& :global(.folded-background){opacity:.5}& :global(.monaco-findInput) textarea{min-height:unset;resize:none}& span{padding:0}}}.editorTools{@apply bg-base}}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
4
|
+
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
|
|
5
|
+
import _toArray from '@babel/runtime/helpers/toArray';
|
|
6
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
7
|
+
import { useIsDark, useResizeObserver, useDebounce, Section } from '@react-fabric/core';
|
|
8
|
+
import { isString, isEmpty } from '@react-fabric/utilities';
|
|
9
|
+
import classNames from 'classnames';
|
|
10
|
+
import { useState, useLayoutEffect, useCallback, useDeferredValue, useMemo, useImperativeHandle } from 'react';
|
|
11
|
+
import MonacoEditor from 'react-monaco-editor';
|
|
12
|
+
import classes from './CodeEditor.module.css';
|
|
13
|
+
import { jsx } from 'react/jsx-runtime';
|
|
14
|
+
|
|
15
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
16
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
17
|
+
var CodeEditor = function CodeEditor(_ref) {
|
|
18
|
+
var ref = _ref.ref,
|
|
19
|
+
value = _ref.value,
|
|
20
|
+
schema = _ref.schema,
|
|
21
|
+
required = _ref.required,
|
|
22
|
+
readOnly = _ref.readOnly,
|
|
23
|
+
minimal = _ref.minimal,
|
|
24
|
+
onChange = _ref.onChange,
|
|
25
|
+
_ref$language = _ref.language,
|
|
26
|
+
language = _ref$language === void 0 ? "json" : _ref$language;
|
|
27
|
+
var _useState = useState(),
|
|
28
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
29
|
+
editorRef = _useState2[0],
|
|
30
|
+
setEditorRef = _useState2[1];
|
|
31
|
+
var _useState3 = useState(),
|
|
32
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
33
|
+
monacoRef = _useState4[0],
|
|
34
|
+
setMonacoRef = _useState4[1];
|
|
35
|
+
var isDark = useIsDark();
|
|
36
|
+
|
|
37
|
+
/** ***************** watch theme change *******************/
|
|
38
|
+
var _useState5 = useState(""),
|
|
39
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
40
|
+
theme = _useState6[0],
|
|
41
|
+
setTheme = _useState6[1];
|
|
42
|
+
useLayoutEffect(function () {
|
|
43
|
+
editorRef && setTheme(isDark ? "vs-dark" : "light");
|
|
44
|
+
}, [isDark, editorRef]);
|
|
45
|
+
|
|
46
|
+
/** ***************** watch editor container resize *******************/
|
|
47
|
+
var resizeHandler = useCallback(function (size) {
|
|
48
|
+
return editorRef === null || editorRef === void 0 ? void 0 : editorRef.layout(size);
|
|
49
|
+
}, [editorRef]);
|
|
50
|
+
var containerRef = useResizeObserver(resizeHandler);
|
|
51
|
+
|
|
52
|
+
/** ***************** defer value and pass to editor as defaultValue *******************/
|
|
53
|
+
var deferredValue = useDeferredValue(value);
|
|
54
|
+
var codeValue = useMemo(function () {
|
|
55
|
+
return isString(deferredValue) ? deferredValue : JSON.stringify(deferredValue, null, 4);
|
|
56
|
+
}, [deferredValue]);
|
|
57
|
+
var handleChange = useDebounce(function (value) {
|
|
58
|
+
var model = editorRef === null || editorRef === void 0 ? void 0 : editorRef.getModel();
|
|
59
|
+
if (model) {
|
|
60
|
+
var markers = monacoRef === null || monacoRef === void 0 ? void 0 : monacoRef.editor.getModelMarkers({
|
|
61
|
+
owner: model.getLanguageId()
|
|
62
|
+
});
|
|
63
|
+
(markers === null || markers === void 0 ? void 0 : markers.filter(function (m) {
|
|
64
|
+
return m.severity > 7;
|
|
65
|
+
}).length) === 0 && (onChange === null || onChange === void 0 ? void 0 : onChange(value));
|
|
66
|
+
}
|
|
67
|
+
}, [onChange, editorRef], 1000);
|
|
68
|
+
useImperativeHandle(ref, function () {
|
|
69
|
+
return {
|
|
70
|
+
getValue: function getValue() {
|
|
71
|
+
return editorRef === null || editorRef === void 0 ? void 0 : editorRef.getValue();
|
|
72
|
+
},
|
|
73
|
+
validate: function validate() {
|
|
74
|
+
var model = editorRef === null || editorRef === void 0 ? void 0 : editorRef.getModel();
|
|
75
|
+
if (model) {
|
|
76
|
+
var markers = monacoRef === null || monacoRef === void 0 ? void 0 : monacoRef.editor.getModelMarkers({
|
|
77
|
+
owner: model.getLanguageId()
|
|
78
|
+
});
|
|
79
|
+
return (markers === null || markers === void 0 ? void 0 : markers.filter(function (m) {
|
|
80
|
+
return m.severity > 8;
|
|
81
|
+
}).length) === 0;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
var val = editorRef === null || editorRef === void 0 ? void 0 : editorRef.getValue();
|
|
85
|
+
if (language === "json") val = JSON.parse(val);
|
|
86
|
+
return required ? !isEmpty(val) : true;
|
|
87
|
+
} catch (_unused) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}, [required, language]);
|
|
93
|
+
var schemaUri = useCallback(function (monaco) {
|
|
94
|
+
if (schema) {
|
|
95
|
+
var _schema = _toArray(schema),
|
|
96
|
+
main = _schema[0],
|
|
97
|
+
rest = _schema.slice(1);
|
|
98
|
+
// configure the JSON language support with schemas and schema associations
|
|
99
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
100
|
+
validate: true,
|
|
101
|
+
allowComments: false,
|
|
102
|
+
schemas: [_objectSpread({
|
|
103
|
+
fileMatch: ["*"]
|
|
104
|
+
}, main)].concat(_toConsumableArray(rest))
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}, [schema]);
|
|
108
|
+
var resetSchema = useCallback(function (_, monaco) {
|
|
109
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
110
|
+
validate: true,
|
|
111
|
+
allowComments: false,
|
|
112
|
+
schemas: []
|
|
113
|
+
});
|
|
114
|
+
}, []);
|
|
115
|
+
return /*#__PURE__*/jsx(Section, {
|
|
116
|
+
children: /*#__PURE__*/jsx("div", {
|
|
117
|
+
ref: containerRef,
|
|
118
|
+
className: classNames(classes.codeEditor, "area-content"),
|
|
119
|
+
children: /*#__PURE__*/jsx(MonacoEditor, {
|
|
120
|
+
editorDidMount: function editorDidMount(e, m) {
|
|
121
|
+
return [!!e && setEditorRef(e), !!m && setMonacoRef(m)];
|
|
122
|
+
},
|
|
123
|
+
editorWillMount: schemaUri,
|
|
124
|
+
editorWillUnmount: resetSchema,
|
|
125
|
+
value: codeValue,
|
|
126
|
+
language: language,
|
|
127
|
+
onChange: handleChange,
|
|
128
|
+
theme: theme,
|
|
129
|
+
className: classes.editor,
|
|
130
|
+
options: {
|
|
131
|
+
readOnly: readOnly,
|
|
132
|
+
minimap: {
|
|
133
|
+
enabled: !minimal
|
|
134
|
+
},
|
|
135
|
+
scrollBeyondLastLine: false,
|
|
136
|
+
folding: !minimal,
|
|
137
|
+
lineNumbers: minimal ? "off" : undefined,
|
|
138
|
+
wordWrap: "on",
|
|
139
|
+
fontFamily: 'Menlo, Monaco, "Courier New", monospace'
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export { CodeEditor };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer util{.codeEditor{border:solid transparent;border-width:1px 1px 2px;direction:ltr;overflow:hidden;&:has(:global(.monaco-editor.focused)){border-color:theme(borderColor.primary.500)}.editor{&>:global(.monaco-editor){--vscode-menu-background:theme(colors.tint.50)!important;--vscode-menu-border:theme(borderColor.base)!important;--vscode-focusBorder:transparent!important;--vscode-menu-selectionBackground:color(from var(--primary) srgb r g b/80%)!important;--vscode-editor-background:var(--fabric-bg)!important;--vscode-editor-foreground:var(--fabric-text)!important;--vscode-breadcrumb-background:var(--fabric-bg)!important;--vscode-editorGutter-background:color(from theme(colors.tint.50) srgb r g g/50%)!important;--vscode-minimapSlider-background:color(from var(--tint) srgb r g b/20%)!important;--vscode-minimapSlider-hoverBackground:color(from var(--tint) srgb r g b/25%)!important;--vscode-minimapSlider-activeBackground:color(from var(--tint) srgb r g b/30%)!important;--vscode-input-border:var(--primary)!important;--vscode-editorStickyScroll-background:var(--fabric-bg)!important;--vscode-editorMarkerNavigation-background:var(--fabric-bg)!important;--vscode-editor-wordHighlightTextBackground:color(from theme(colors.accent.700) srgb r g b/20%)!important}& :global(.minimap-decorations-layer){background-color:color(from theme(colors.tint.50) srgb r g g/50%)!important}& :global(.folded-background){opacity:.5}& :global(.monaco-findInput) textarea{min-height:unset;resize:none}& span{padding:0}}}.editorTools{@apply bg-base}}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
2
|
+
export interface MonacoEditorRef {
|
|
3
|
+
validate: () => boolean;
|
|
4
|
+
getValue: () => string | undefined;
|
|
5
|
+
}
|
|
6
|
+
export interface EditorProps {
|
|
7
|
+
value?: string | AnyObject;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
readOnly?: boolean;
|
|
10
|
+
minimal?: boolean;
|
|
11
|
+
schema?: Array<{
|
|
12
|
+
uri: string;
|
|
13
|
+
schema: KeyValue;
|
|
14
|
+
}>;
|
|
15
|
+
language?: "json" | "css" | "html" | "text" | "markdown";
|
|
16
|
+
onChange?: (value: string) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare const CodeEditor: ({ ref, value, schema, required, readOnly, minimal, onChange, language, }: EditorProps & RefProp<MonacoEditorRef>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CodeEditor } from "./components/CodeEditor";
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@react-fabric/monaco",
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
|
+
"description": "RUF: Monaco editor",
|
|
5
|
+
"author": "Adarsh Pastakia <adarshpastakia@outlook.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": "https://github.com/adarshpastakia/react-ui-framework/tree/main/packages/monaco",
|
|
8
|
+
"source": "src/index.ts",
|
|
9
|
+
"main": "dist/cjs/index.js",
|
|
10
|
+
"module": "dist/esm/index.js",
|
|
11
|
+
"types": "dist/types/index.d.ts",
|
|
12
|
+
"directories": {
|
|
13
|
+
"src": "src",
|
|
14
|
+
"test": "tests"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"src",
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"registry": "https://registry.npmjs.org/"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"makelink": "yarn link",
|
|
26
|
+
"removelink": "yarn unlink",
|
|
27
|
+
"prebuild": "rm -rf ./dist",
|
|
28
|
+
"build:dts": "tsc -p ./tsconfig.build.json",
|
|
29
|
+
"build:rollup": "rollup -c ../../rollup.config.mjs",
|
|
30
|
+
"build": "npm-run-all -p build:rollup build:dts",
|
|
31
|
+
"watch:dts": "tsc -w -p ./tsconfig.build.json",
|
|
32
|
+
"watch:rollup": "rollup -w -c ../../rollup.config.mjs",
|
|
33
|
+
"watch": "npm-run-all -p watch:rollup watch:dts"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@react-fabric/core": "^1.0.0-beta.0",
|
|
37
|
+
"@react-fabric/utilities": "^1.0.0-beta.0",
|
|
38
|
+
"classnames": "^2.5.1",
|
|
39
|
+
"react-monaco-editor": "^0.56.2"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"i18next": "^23.15.1",
|
|
43
|
+
"react": ">=18.0.0 <20.0.0",
|
|
44
|
+
"react-dom": ">=18.0.0 <20.0.0",
|
|
45
|
+
"react-i18next": "^15.0.2"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"monaco-editor": "^0.52.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18.12.0",
|
|
52
|
+
"npm": ">=8.19.0"
|
|
53
|
+
},
|
|
54
|
+
"gitHead": "83fa79064b1d57e71149005432192d506810bbda"
|
|
55
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* React Fabric
|
|
3
|
+
* @version: 1.0.0
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* The MIT License (MIT)
|
|
7
|
+
* Copyright (c) 2024 Adarsh Pastakia
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
10
|
+
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
11
|
+
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
13
|
+
* subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
16
|
+
* portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
19
|
+
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
20
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/* stylelint-disable custom-property-pattern */
|
|
25
|
+
|
|
26
|
+
@layer util {
|
|
27
|
+
.codeEditor {
|
|
28
|
+
direction: ltr;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
border: 1px solid transparent;
|
|
31
|
+
border-bottom-width: 2px;
|
|
32
|
+
|
|
33
|
+
&:has(:global(.monaco-editor.focused)) {
|
|
34
|
+
border-color: theme(borderColor.primary.500);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.editor {
|
|
38
|
+
& > :global(.monaco-editor) {
|
|
39
|
+
--vscode-menu-background: theme(colors.tint.50) !important;
|
|
40
|
+
--vscode-menu-border: theme(borderColor.base) !important;
|
|
41
|
+
--vscode-focusBorder: transparent !important;
|
|
42
|
+
--vscode-menu-selectionBackground: color(
|
|
43
|
+
from var(--primary) srgb r g b / 80%
|
|
44
|
+
) !important;
|
|
45
|
+
--vscode-editor-background: var(--fabric-bg) !important;
|
|
46
|
+
--vscode-editor-foreground: var(--fabric-text) !important;
|
|
47
|
+
--vscode-breadcrumb-background: var(--fabric-bg) !important;
|
|
48
|
+
--vscode-editorGutter-background: color(
|
|
49
|
+
from theme(colors.tint.50) srgb r g g / 50%
|
|
50
|
+
) !important;
|
|
51
|
+
--vscode-minimapSlider-background: color(
|
|
52
|
+
from var(--tint) srgb r g b / 20%
|
|
53
|
+
) !important;
|
|
54
|
+
--vscode-minimapSlider-hoverBackground: color(
|
|
55
|
+
from var(--tint) srgb r g b / 25%
|
|
56
|
+
) !important;
|
|
57
|
+
--vscode-minimapSlider-activeBackground: color(
|
|
58
|
+
from var(--tint) srgb r g b / 30%
|
|
59
|
+
) !important;
|
|
60
|
+
--vscode-input-border: var(--primary) !important;
|
|
61
|
+
--vscode-editorStickyScroll-background: var(--fabric-bg) !important;
|
|
62
|
+
--vscode-editorMarkerNavigation-background: var(--fabric-bg) !important;
|
|
63
|
+
--vscode-editor-wordHighlightTextBackground: color(
|
|
64
|
+
from theme(colors.accent.700) srgb r g b / 20%
|
|
65
|
+
) !important;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
& :global(.minimap-decorations-layer) {
|
|
69
|
+
background-color: color(
|
|
70
|
+
from theme(colors.tint.50) srgb r g g / 50%
|
|
71
|
+
) !important;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
& :global(.folded-background) {
|
|
75
|
+
opacity: 0.5;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
& :global(.monaco-findInput) textarea {
|
|
79
|
+
resize: initial;
|
|
80
|
+
min-height: unset;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
& span {
|
|
84
|
+
padding: 0;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.editorTools {
|
|
90
|
+
@apply bg-base;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* React Fabric
|
|
3
|
+
* @version: 1.0.0
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* The MIT License (MIT)
|
|
7
|
+
* Copyright (c) 2024 Adarsh Pastakia
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
10
|
+
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
11
|
+
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
13
|
+
* subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
16
|
+
* portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
19
|
+
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
20
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
Section,
|
|
26
|
+
useDebounce,
|
|
27
|
+
useIsDark,
|
|
28
|
+
useResizeObserver,
|
|
29
|
+
} from "@react-fabric/core";
|
|
30
|
+
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
31
|
+
import { isEmpty, isString } from "@react-fabric/utilities";
|
|
32
|
+
import classNames from "classnames";
|
|
33
|
+
import type monacoEditor from "monaco-editor";
|
|
34
|
+
import {
|
|
35
|
+
useCallback,
|
|
36
|
+
useDeferredValue,
|
|
37
|
+
useImperativeHandle,
|
|
38
|
+
useLayoutEffect,
|
|
39
|
+
useMemo,
|
|
40
|
+
useState,
|
|
41
|
+
} from "react";
|
|
42
|
+
import MonacoEditor from "react-monaco-editor";
|
|
43
|
+
import classes from "./CodeEditor.module.css";
|
|
44
|
+
|
|
45
|
+
export interface MonacoEditorRef {
|
|
46
|
+
validate: () => boolean;
|
|
47
|
+
getValue: () => string | undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface EditorProps {
|
|
51
|
+
value?: string | AnyObject;
|
|
52
|
+
|
|
53
|
+
required?: boolean;
|
|
54
|
+
readOnly?: boolean;
|
|
55
|
+
|
|
56
|
+
minimal?: boolean;
|
|
57
|
+
|
|
58
|
+
schema?: Array<{ uri: string; schema: KeyValue }>;
|
|
59
|
+
|
|
60
|
+
language?: "json" | "css" | "html" | "text" | "markdown";
|
|
61
|
+
|
|
62
|
+
onChange?: (value: string) => void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const CodeEditor = ({
|
|
66
|
+
ref,
|
|
67
|
+
value,
|
|
68
|
+
schema,
|
|
69
|
+
required,
|
|
70
|
+
readOnly,
|
|
71
|
+
minimal,
|
|
72
|
+
onChange,
|
|
73
|
+
language = "json",
|
|
74
|
+
}: EditorProps & RefProp<MonacoEditorRef>) => {
|
|
75
|
+
const [editorRef, setEditorRef] = useState<AnyObject>();
|
|
76
|
+
const [monacoRef, setMonacoRef] = useState<typeof monacoEditor>();
|
|
77
|
+
const isDark = useIsDark();
|
|
78
|
+
|
|
79
|
+
/** ***************** watch theme change *******************/
|
|
80
|
+
const [theme, setTheme] = useState("");
|
|
81
|
+
useLayoutEffect(() => {
|
|
82
|
+
editorRef && setTheme(isDark ? "vs-dark" : "light");
|
|
83
|
+
}, [isDark, editorRef]);
|
|
84
|
+
|
|
85
|
+
/** ***************** watch editor container resize *******************/
|
|
86
|
+
const resizeHandler = useCallback(
|
|
87
|
+
(size: AnyObject) => editorRef?.layout(size),
|
|
88
|
+
[editorRef],
|
|
89
|
+
);
|
|
90
|
+
const containerRef = useResizeObserver(resizeHandler);
|
|
91
|
+
|
|
92
|
+
/** ***************** defer value and pass to editor as defaultValue *******************/
|
|
93
|
+
const deferredValue = useDeferredValue(value);
|
|
94
|
+
const codeValue = useMemo(
|
|
95
|
+
() =>
|
|
96
|
+
isString(deferredValue)
|
|
97
|
+
? deferredValue
|
|
98
|
+
: JSON.stringify(deferredValue, null, 4),
|
|
99
|
+
[deferredValue],
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const handleChange = useDebounce(
|
|
103
|
+
(value: string) => {
|
|
104
|
+
const model = editorRef?.getModel();
|
|
105
|
+
if (model) {
|
|
106
|
+
const markers = monacoRef?.editor.getModelMarkers({
|
|
107
|
+
owner: model.getLanguageId(),
|
|
108
|
+
});
|
|
109
|
+
markers?.filter((m) => m.severity > 7).length === 0 &&
|
|
110
|
+
onChange?.(value);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
[onChange, editorRef],
|
|
114
|
+
1000,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
useImperativeHandle(
|
|
118
|
+
ref,
|
|
119
|
+
() => ({
|
|
120
|
+
getValue() {
|
|
121
|
+
return editorRef?.getValue();
|
|
122
|
+
},
|
|
123
|
+
validate() {
|
|
124
|
+
const model = editorRef?.getModel();
|
|
125
|
+
if (model) {
|
|
126
|
+
const markers = monacoRef?.editor.getModelMarkers({
|
|
127
|
+
owner: model.getLanguageId(),
|
|
128
|
+
});
|
|
129
|
+
return markers?.filter((m) => m.severity > 8).length === 0;
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
let val = editorRef?.getValue();
|
|
133
|
+
if (language === "json") val = JSON.parse(val);
|
|
134
|
+
return required ? !isEmpty(val) : true;
|
|
135
|
+
} catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
}),
|
|
140
|
+
[required, language],
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const schemaUri = useCallback(
|
|
144
|
+
(monaco: typeof monacoEditor) => {
|
|
145
|
+
if (schema) {
|
|
146
|
+
const [main, ...rest] = schema;
|
|
147
|
+
// configure the JSON language support with schemas and schema associations
|
|
148
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
149
|
+
validate: true,
|
|
150
|
+
allowComments: false,
|
|
151
|
+
schemas: [
|
|
152
|
+
{
|
|
153
|
+
fileMatch: ["*"], // associate with our model
|
|
154
|
+
...main,
|
|
155
|
+
},
|
|
156
|
+
...rest,
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
[schema],
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const resetSchema = useCallback((_: unknown, monaco: typeof monacoEditor) => {
|
|
165
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
166
|
+
validate: true,
|
|
167
|
+
allowComments: false,
|
|
168
|
+
schemas: [],
|
|
169
|
+
});
|
|
170
|
+
}, []);
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<Section>
|
|
174
|
+
<div
|
|
175
|
+
ref={containerRef}
|
|
176
|
+
className={classNames(classes.codeEditor, "area-content")}
|
|
177
|
+
>
|
|
178
|
+
<MonacoEditor
|
|
179
|
+
editorDidMount={(e, m) => [
|
|
180
|
+
!!e && setEditorRef(e),
|
|
181
|
+
!!m && setMonacoRef(m),
|
|
182
|
+
]}
|
|
183
|
+
editorWillMount={schemaUri}
|
|
184
|
+
editorWillUnmount={resetSchema}
|
|
185
|
+
value={codeValue}
|
|
186
|
+
language={language}
|
|
187
|
+
onChange={handleChange}
|
|
188
|
+
theme={theme}
|
|
189
|
+
className={classes.editor}
|
|
190
|
+
options={{
|
|
191
|
+
readOnly,
|
|
192
|
+
minimap: {
|
|
193
|
+
enabled: !minimal,
|
|
194
|
+
},
|
|
195
|
+
scrollBeyondLastLine: false,
|
|
196
|
+
folding: !minimal,
|
|
197
|
+
lineNumbers: minimal ? "off" : undefined,
|
|
198
|
+
wordWrap: "on",
|
|
199
|
+
fontFamily: 'Menlo, Monaco, "Courier New", monospace',
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
203
|
+
</Section>
|
|
204
|
+
);
|
|
205
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* React Fabric
|
|
3
|
+
* @version: 1.0.0
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* The MIT License (MIT)
|
|
7
|
+
* Copyright (c) 2024 Adarsh Pastakia
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
10
|
+
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
11
|
+
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
13
|
+
* subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
16
|
+
* portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
19
|
+
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
20
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export { CodeEditor } from "./components/CodeEditor";
|