@codenotch/codenotch.react 1.0.81 → 2.0.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/README.md +57 -19
- package/dist/components/CodeEditor.d.ts +1 -1
- package/dist/components/CodeEditor.d.ts.map +1 -1
- package/dist/components/CodeEditor.js +66 -64
- package/dist/index.d.ts +86 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +158 -26
- package/dist/models/Codenotch.d.ts +30 -13
- package/dist/models/Codenotch.d.ts.map +1 -1
- package/package.json +46 -44
- package/src/components/CodeEditor.tsx +204 -203
- package/src/index.ts +531 -386
- package/src/models/Codenotch.ts +31 -13
- package/dist/components/Auml.d.ts +0 -46
- package/dist/components/Auml.d.ts.map +0 -1
- package/dist/components/Auml.js +0 -208
- package/dist/models/AppManifestModels.d.ts +0 -46
- package/dist/models/AppManifestModels.d.ts.map +0 -1
- package/dist/models/AppManifestModels.js +0 -2
- package/dist/models/ProjectManifestModels.d.ts +0 -126
- package/dist/models/ProjectManifestModels.d.ts.map +0 -1
- package/dist/models/ProjectManifestModels.js +0 -158
- package/dist/utils/I18nUtils.d.ts +0 -7
- package/dist/utils/I18nUtils.d.ts.map +0 -1
- package/dist/utils/I18nUtils.js +0 -37
- package/src/models/AppManifestModels.ts +0 -54
|
@@ -1,203 +1,204 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { ICodenotchEnv } from "..";
|
|
3
|
-
|
|
4
|
-
interface ICodeEditorProps {
|
|
5
|
-
/** Codenotch environment; only used to follow the current theme (`vs`/`vs-dark`). */
|
|
6
|
-
env?: ICodenotchEnv;
|
|
7
|
-
style?: React.CSSProperties;
|
|
8
|
-
className?: string;
|
|
9
|
-
/** Text content of the editor. */
|
|
10
|
-
value?: string;
|
|
11
|
-
/** Monaco language id (e.g. `'typescript'`, `'json'`, `'xml'`). Defaults to `'plaintext'`. */
|
|
12
|
-
language?: string;
|
|
13
|
-
readOnly?: boolean;
|
|
14
|
-
/** Called (debounced, 300 ms) when the user edits the content. */
|
|
15
|
-
onChange?: (value: string) => void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Light Monaco code editor embedded in a sandboxed iframe
|
|
20
|
-
* (Monaco is loaded from the jsdelivr CDN — requires network access).
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* <CodeEditor env={cn.env} language="json" value={text} onChange={setText} />
|
|
24
|
-
*/
|
|
25
|
-
export default class CodeEditor extends React.Component<ICodeEditorProps> {
|
|
26
|
-
private isIframeReady = false;
|
|
27
|
-
private onChangeTimeoutHandle: any = null;
|
|
28
|
-
private onMessageHandler: any;
|
|
29
|
-
refFrame = React.createRef<HTMLIFrameElement>();
|
|
30
|
-
|
|
31
|
-
constructor(props: ICodeEditorProps) {
|
|
32
|
-
super(props);
|
|
33
|
-
this.onMessageHandler = this.handleMessage.bind(this);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
setValue(value: string) {
|
|
37
|
-
if (this.isIframeReady) {
|
|
38
|
-
this.postToIframe({
|
|
39
|
-
type: 'update',
|
|
40
|
-
value: value,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
componentDidMount(): void {
|
|
46
|
-
window.addEventListener('message', this.onMessageHandler);
|
|
47
|
-
this.writeIframe();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
componentWillUnmount(): void {
|
|
51
|
-
window.removeEventListener('message', this.onMessageHandler);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
componentDidUpdate(prevProps: ICodeEditorProps): void {
|
|
55
|
-
const changed = (
|
|
56
|
-
prevProps.value !== this.props.value ||
|
|
57
|
-
prevProps.language !== this.props.language ||
|
|
58
|
-
prevProps.readOnly !== this.props.readOnly
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
if (changed && this.isIframeReady) {
|
|
62
|
-
let isDark = this.props.env?.theme === 'dark';
|
|
63
|
-
this.postToIframe({
|
|
64
|
-
type: 'update',
|
|
65
|
-
value: this.props.value ?? '',
|
|
66
|
-
language: this.props.language || 'plaintext',
|
|
67
|
-
readOnly: !!this.props.readOnly,
|
|
68
|
-
theme: isDark ? 'vs-dark' : 'vs'
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private handleMessage(event: MessageEvent) {
|
|
75
|
-
const data = event.data as any;
|
|
76
|
-
if (!data || typeof data !== 'object') return;
|
|
77
|
-
if (data.__from !== 'MonacoIframe') return;
|
|
78
|
-
|
|
79
|
-
switch (data.type) {
|
|
80
|
-
case 'ready': {
|
|
81
|
-
this.isIframeReady = true;
|
|
82
|
-
// send initial payload
|
|
83
|
-
this.postToIframe({
|
|
84
|
-
type: 'init',
|
|
85
|
-
value: this.props.value ?? '',
|
|
86
|
-
language: this.props.language || 'plaintext',
|
|
87
|
-
readOnly: !!this.props.readOnly,
|
|
88
|
-
theme: this.props.env?.theme === 'dark' ? 'vs-dark' : 'vs'
|
|
89
|
-
});
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
case 'change': {
|
|
93
|
-
const next = String(data.value ?? '');
|
|
94
|
-
if (this.onChangeTimeoutHandle) {
|
|
95
|
-
clearTimeout(this.onChangeTimeoutHandle);
|
|
96
|
-
}
|
|
97
|
-
this.onChangeTimeoutHandle = setTimeout(() => {
|
|
98
|
-
this.props.onChange?.(next);
|
|
99
|
-
}, 300);
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
private postToIframe(message: any) {
|
|
107
|
-
const w = this.refFrame.current?.contentWindow;
|
|
108
|
-
if (!w) return;
|
|
109
|
-
w.postMessage({ __from: 'MonacoIframe', ...message }, '*');
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private writeIframe() {
|
|
113
|
-
const iframe = this.refFrame.current;
|
|
114
|
-
if (!iframe) return;
|
|
115
|
-
|
|
116
|
-
const vsBase = 'https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs';
|
|
117
|
-
const html = `<!DOCTYPE html>
|
|
118
|
-
<html>
|
|
119
|
-
<head>
|
|
120
|
-
<meta charset="utf-8" />
|
|
121
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
122
|
-
<style>
|
|
123
|
-
html, body, #container { height: 100%; width: 100%; margin: 0; padding: 0; overflow: hidden; }
|
|
124
|
-
</style>
|
|
125
|
-
<script>
|
|
126
|
-
(function(){
|
|
127
|
-
var vsBase = ${JSON.stringify(vsBase)};
|
|
128
|
-
// AMD loader
|
|
129
|
-
var s = document.createElement('script');
|
|
130
|
-
s.src = vsBase + '/loader.js';
|
|
131
|
-
s.onload = function(){
|
|
132
|
-
// Configure and load monaco
|
|
133
|
-
window.require.config({ paths: { vs: vsBase } });
|
|
134
|
-
window.require(['vs/editor/editor.main'], function(){
|
|
135
|
-
var editor;
|
|
136
|
-
|
|
137
|
-
function post(msg){ parent.postMessage(Object.assign({__from:'MonacoIframe'}, msg), '*'); }
|
|
138
|
-
|
|
139
|
-
function ensureEditor(){
|
|
140
|
-
if (editor) return editor;
|
|
141
|
-
editor = monaco.editor.create(document.getElementById('container'), {
|
|
142
|
-
value: '',
|
|
143
|
-
language: 'plaintext',
|
|
144
|
-
theme: 'vs',
|
|
145
|
-
automaticLayout: true,
|
|
146
|
-
minimap: { enabled: false },
|
|
147
|
-
scrollBeyondLastLine: true,
|
|
148
|
-
wordWrap: "on"
|
|
149
|
-
});
|
|
150
|
-
editor.onDidChangeModelContent(function(){
|
|
151
|
-
var v = editor.getValue();
|
|
152
|
-
post({ type: 'change', value: v });
|
|
153
|
-
});
|
|
154
|
-
return editor;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
window.addEventListener('message', function(ev){
|
|
158
|
-
var data = ev.data || {}; if (data.__from !== 'MonacoIframe') return;
|
|
159
|
-
if (data.type === 'init' || data.type === 'update'){
|
|
160
|
-
var ed = ensureEditor();
|
|
161
|
-
if (typeof data.value === 'string' && ed.getValue() !== data.value){ ed.setValue(data.value); }
|
|
162
|
-
if (typeof data.language === 'string') { monaco.editor.setModelLanguage(ed.getModel(), data.language); }
|
|
163
|
-
if (typeof data.theme === 'string') { monaco.editor.setTheme(data.theme); }
|
|
164
|
-
if (typeof data.readOnly === 'boolean') { ed.updateOptions({ readOnly: data.readOnly }); }
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// Signal ready after monaco is loaded
|
|
169
|
-
post({ type: 'ready' });
|
|
170
|
-
});
|
|
171
|
-
};
|
|
172
|
-
document.head.appendChild(s);
|
|
173
|
-
})();
|
|
174
|
-
</script>
|
|
175
|
-
</head>
|
|
176
|
-
<body>
|
|
177
|
-
<div id="container"></div>
|
|
178
|
-
</body>
|
|
179
|
-
</html>`;
|
|
180
|
-
|
|
181
|
-
const doc = iframe.contentWindow?.document;
|
|
182
|
-
if (!doc) return;
|
|
183
|
-
doc.open();
|
|
184
|
-
doc.write(html);
|
|
185
|
-
doc.close();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
render() {
|
|
189
|
-
|
|
190
|
-
style.
|
|
191
|
-
style.
|
|
192
|
-
style.
|
|
193
|
-
style.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ICodenotchEnv } from "..";
|
|
3
|
+
|
|
4
|
+
interface ICodeEditorProps {
|
|
5
|
+
/** Codenotch environment; only used to follow the current theme (`vs`/`vs-dark`). */
|
|
6
|
+
env?: ICodenotchEnv;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
className?: string;
|
|
9
|
+
/** Text content of the editor. */
|
|
10
|
+
value?: string;
|
|
11
|
+
/** Monaco language id (e.g. `'typescript'`, `'json'`, `'xml'`). Defaults to `'plaintext'`. */
|
|
12
|
+
language?: string;
|
|
13
|
+
readOnly?: boolean;
|
|
14
|
+
/** Called (debounced, 300 ms) when the user edits the content. */
|
|
15
|
+
onChange?: (value: string) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Light Monaco code editor embedded in a sandboxed iframe
|
|
20
|
+
* (Monaco is loaded from the jsdelivr CDN — requires network access).
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <CodeEditor env={cn.env} language="json" value={text} onChange={setText} />
|
|
24
|
+
*/
|
|
25
|
+
export default class CodeEditor extends React.Component<ICodeEditorProps> {
|
|
26
|
+
private isIframeReady = false;
|
|
27
|
+
private onChangeTimeoutHandle: any = null;
|
|
28
|
+
private onMessageHandler: any;
|
|
29
|
+
refFrame = React.createRef<HTMLIFrameElement>();
|
|
30
|
+
|
|
31
|
+
constructor(props: ICodeEditorProps) {
|
|
32
|
+
super(props);
|
|
33
|
+
this.onMessageHandler = this.handleMessage.bind(this);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setValue(value: string) {
|
|
37
|
+
if (this.isIframeReady) {
|
|
38
|
+
this.postToIframe({
|
|
39
|
+
type: 'update',
|
|
40
|
+
value: value,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
componentDidMount(): void {
|
|
46
|
+
window.addEventListener('message', this.onMessageHandler);
|
|
47
|
+
this.writeIframe();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
componentWillUnmount(): void {
|
|
51
|
+
window.removeEventListener('message', this.onMessageHandler);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
componentDidUpdate(prevProps: ICodeEditorProps): void {
|
|
55
|
+
const changed = (
|
|
56
|
+
prevProps.value !== this.props.value ||
|
|
57
|
+
prevProps.language !== this.props.language ||
|
|
58
|
+
prevProps.readOnly !== this.props.readOnly
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (changed && this.isIframeReady) {
|
|
62
|
+
let isDark = this.props.env?.theme === 'dark';
|
|
63
|
+
this.postToIframe({
|
|
64
|
+
type: 'update',
|
|
65
|
+
value: this.props.value ?? '',
|
|
66
|
+
language: this.props.language || 'plaintext',
|
|
67
|
+
readOnly: !!this.props.readOnly,
|
|
68
|
+
theme: isDark ? 'vs-dark' : 'vs'
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private handleMessage(event: MessageEvent) {
|
|
75
|
+
const data = event.data as any;
|
|
76
|
+
if (!data || typeof data !== 'object') return;
|
|
77
|
+
if (data.__from !== 'MonacoIframe') return;
|
|
78
|
+
|
|
79
|
+
switch (data.type) {
|
|
80
|
+
case 'ready': {
|
|
81
|
+
this.isIframeReady = true;
|
|
82
|
+
// send initial payload
|
|
83
|
+
this.postToIframe({
|
|
84
|
+
type: 'init',
|
|
85
|
+
value: this.props.value ?? '',
|
|
86
|
+
language: this.props.language || 'plaintext',
|
|
87
|
+
readOnly: !!this.props.readOnly,
|
|
88
|
+
theme: this.props.env?.theme === 'dark' ? 'vs-dark' : 'vs'
|
|
89
|
+
});
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
case 'change': {
|
|
93
|
+
const next = String(data.value ?? '');
|
|
94
|
+
if (this.onChangeTimeoutHandle) {
|
|
95
|
+
clearTimeout(this.onChangeTimeoutHandle);
|
|
96
|
+
}
|
|
97
|
+
this.onChangeTimeoutHandle = setTimeout(() => {
|
|
98
|
+
this.props.onChange?.(next);
|
|
99
|
+
}, 300);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
private postToIframe(message: any) {
|
|
107
|
+
const w = this.refFrame.current?.contentWindow;
|
|
108
|
+
if (!w) return;
|
|
109
|
+
w.postMessage({ __from: 'MonacoIframe', ...message }, '*');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private writeIframe() {
|
|
113
|
+
const iframe = this.refFrame.current;
|
|
114
|
+
if (!iframe) return;
|
|
115
|
+
|
|
116
|
+
const vsBase = 'https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs';
|
|
117
|
+
const html = `<!DOCTYPE html>
|
|
118
|
+
<html>
|
|
119
|
+
<head>
|
|
120
|
+
<meta charset="utf-8" />
|
|
121
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
122
|
+
<style>
|
|
123
|
+
html, body, #container { height: 100%; width: 100%; margin: 0; padding: 0; overflow: hidden; }
|
|
124
|
+
</style>
|
|
125
|
+
<script>
|
|
126
|
+
(function(){
|
|
127
|
+
var vsBase = ${JSON.stringify(vsBase)};
|
|
128
|
+
// AMD loader
|
|
129
|
+
var s = document.createElement('script');
|
|
130
|
+
s.src = vsBase + '/loader.js';
|
|
131
|
+
s.onload = function(){
|
|
132
|
+
// Configure and load monaco
|
|
133
|
+
window.require.config({ paths: { vs: vsBase } });
|
|
134
|
+
window.require(['vs/editor/editor.main'], function(){
|
|
135
|
+
var editor;
|
|
136
|
+
|
|
137
|
+
function post(msg){ parent.postMessage(Object.assign({__from:'MonacoIframe'}, msg), '*'); }
|
|
138
|
+
|
|
139
|
+
function ensureEditor(){
|
|
140
|
+
if (editor) return editor;
|
|
141
|
+
editor = monaco.editor.create(document.getElementById('container'), {
|
|
142
|
+
value: '',
|
|
143
|
+
language: 'plaintext',
|
|
144
|
+
theme: 'vs',
|
|
145
|
+
automaticLayout: true,
|
|
146
|
+
minimap: { enabled: false },
|
|
147
|
+
scrollBeyondLastLine: true,
|
|
148
|
+
wordWrap: "on"
|
|
149
|
+
});
|
|
150
|
+
editor.onDidChangeModelContent(function(){
|
|
151
|
+
var v = editor.getValue();
|
|
152
|
+
post({ type: 'change', value: v });
|
|
153
|
+
});
|
|
154
|
+
return editor;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
window.addEventListener('message', function(ev){
|
|
158
|
+
var data = ev.data || {}; if (data.__from !== 'MonacoIframe') return;
|
|
159
|
+
if (data.type === 'init' || data.type === 'update'){
|
|
160
|
+
var ed = ensureEditor();
|
|
161
|
+
if (typeof data.value === 'string' && ed.getValue() !== data.value){ ed.setValue(data.value); }
|
|
162
|
+
if (typeof data.language === 'string') { monaco.editor.setModelLanguage(ed.getModel(), data.language); }
|
|
163
|
+
if (typeof data.theme === 'string') { monaco.editor.setTheme(data.theme); }
|
|
164
|
+
if (typeof data.readOnly === 'boolean') { ed.updateOptions({ readOnly: data.readOnly }); }
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Signal ready after monaco is loaded
|
|
169
|
+
post({ type: 'ready' });
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
document.head.appendChild(s);
|
|
173
|
+
})();
|
|
174
|
+
</script>
|
|
175
|
+
</head>
|
|
176
|
+
<body>
|
|
177
|
+
<div id="container"></div>
|
|
178
|
+
</body>
|
|
179
|
+
</html>`;
|
|
180
|
+
|
|
181
|
+
const doc = iframe.contentWindow?.document;
|
|
182
|
+
if (!doc) return;
|
|
183
|
+
doc.open();
|
|
184
|
+
doc.write(html);
|
|
185
|
+
doc.close();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
render() {
|
|
189
|
+
// Never mutate props: copy the style object before applying defaults.
|
|
190
|
+
const style: React.CSSProperties = { ...this.props.style };
|
|
191
|
+
style.width = style.width || '100%';
|
|
192
|
+
style.height = style.height || '100%';
|
|
193
|
+
style.border = style.border || '0';
|
|
194
|
+
style.outline = style.outline || '0';
|
|
195
|
+
|
|
196
|
+
return <iframe
|
|
197
|
+
style={style}
|
|
198
|
+
title="Codenotch"
|
|
199
|
+
ref={this.refFrame}
|
|
200
|
+
className={this.props.className}
|
|
201
|
+
sandbox="allow-scripts allow-same-origin"
|
|
202
|
+
/>
|
|
203
|
+
}
|
|
204
|
+
}
|