Skip to content

Commit f30adcb

Browse files
authored
fix(code editor): remount when readOnly change (#1179)
* fix(code editor): remount when readOnly change * fix: remove console
1 parent 0cdbf78 commit f30adcb

File tree

2 files changed

+46
-20
lines changed

2 files changed

+46
-20
lines changed

sandpack-react/src/components/CodeEditor/CodeMirror.stories.tsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { SandpackProvider } from "../../contexts/sandpackContext";
88

99
import * as mocks from "./languages-mocks";
1010

11-
import { CodeEditor } from "./index";
11+
import { CodeEditor, SandpackCodeEditor } from "./index";
12+
import { useSandpack } from "../../hooks";
1213
const stories = storiesOf("components/CodeMirror", module);
1314

1415
Object.entries(mocks).forEach(([languageName, mockFile]) =>
@@ -24,6 +25,37 @@ Object.entries(mocks).forEach(([languageName, mockFile]) =>
2425
))
2526
);
2627

28+
stories.add("Ready only", () => {
29+
return (
30+
<>
31+
<SandpackProvider
32+
files={{
33+
"/index.js": {
34+
code: 'const title = "This is a simple code editor"',
35+
},
36+
}}
37+
>
38+
<ReadOnlyEditor />
39+
</SandpackProvider>
40+
</>
41+
);
42+
});
43+
44+
const ReadOnlyEditor = () => {
45+
const [isReadOnly, setIsReadOnly] = React.useState(false);
46+
const { sandpack } = useSandpack();
47+
48+
return (
49+
<>
50+
<button onClick={() => setIsReadOnly(!isReadOnly)} type="button">
51+
Toggle read only ({isReadOnly ? "true" : "false"})
52+
</button>
53+
<SandpackCodeEditor readOnly={isReadOnly} />
54+
<pre>{JSON.stringify(sandpack.files, null, 2)}</pre>
55+
</>
56+
);
57+
};
58+
2759
stories.add("CustomLanguageShell", () => (
2860
<SandpackProvider>
2961
<CodeEditor

sandpack-react/src/components/CodeEditor/CodeMirror.tsx

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export const CodeMirror = React.forwardRef<CodeMirrorRef, CodeMirrorProps>(
184184
);
185185

186186
React.useEffect(() => {
187-
if (!wrapper.current || !shouldInitEditor) return;
187+
if (!wrapper.current || !shouldInitEditor || readOnly) return;
188188

189189
const parentDiv = wrapper.current;
190190
const existingPlaceholder = parentDiv.querySelector(
@@ -198,16 +198,6 @@ export const CodeMirror = React.forwardRef<CodeMirrorRef, CodeMirrorProps>(
198198
doc: code,
199199
extensions: [],
200200
parent: parentDiv,
201-
dispatch: (tr): void => {
202-
view.update([tr]);
203-
204-
if (tr.docChanged) {
205-
const newCode = tr.newDoc.sliceString(0, tr.newDoc.length);
206-
207-
setInternalCode(newCode);
208-
onCodeUpdate?.(newCode);
209-
}
210-
},
211201
});
212202

213203
view.contentDOM.setAttribute("data-gramm", "false");
@@ -216,23 +206,18 @@ export const CodeMirror = React.forwardRef<CodeMirrorRef, CodeMirrorProps>(
216206
"aria-label",
217207
filePath ? `Code Editor for ${getFileName(filePath)}` : `Code Editor`
218208
);
219-
220-
if (readOnly) {
221-
view.contentDOM.classList.add("cm-readonly");
222-
} else {
223-
view.contentDOM.setAttribute("tabIndex", "-1");
224-
}
209+
view.contentDOM.setAttribute("tabIndex", "-1");
225210

226211
cmView.current = view;
227212

228213
return (): void => {
229214
cmView.current?.destroy();
230215
};
231216
// eslint-disable-next-line react-hooks/exhaustive-deps
232-
}, [shouldInitEditor]);
217+
}, [shouldInitEditor, readOnly]);
233218

234219
React.useEffect(() => {
235-
if (cmView.current) {
220+
if (cmView.current && !readOnly) {
236221
const customCommandsKeymap: KeyBinding[] = [
237222
{
238223
key: "Tab",
@@ -294,6 +279,15 @@ export const CodeMirror = React.forwardRef<CodeMirrorRef, CodeMirrorProps>(
294279

295280
getEditorTheme(),
296281
syntaxHighlighting(highlightTheme),
282+
283+
EditorView.updateListener.of((update) => {
284+
if (update.docChanged) {
285+
const newCode = update.state.doc.toString();
286+
287+
setInternalCode(newCode);
288+
onCodeUpdate?.(newCode);
289+
}
290+
}),
297291
];
298292

299293
if (readOnly) {

0 commit comments

Comments
 (0)