Skip to content

Commit b4f1316

Browse files
committed
Check to see if lazy loading/peer dep change work
1 parent 4034ad9 commit b4f1316

File tree

4 files changed

+86
-31
lines changed

4 files changed

+86
-31
lines changed

package-lock.json

Lines changed: 13 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/module/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"@patternfly/react-styles": "^6.1.0",
4141
"@segment/analytics-next": "^1.76.0",
4242
"clsx": "^2.1.0",
43-
"monaco-editor": "^0.54.0",
4443
"path-browserify": "^1.0.1",
4544
"posthog-js": "^1.194.4",
4645
"react-markdown": "^9.0.1",
@@ -53,7 +52,16 @@
5352
},
5453
"peerDependencies": {
5554
"react": "^18 || ^19",
56-
"react-dom": "^18 || ^19"
55+
"react-dom": "^18 || ^19",
56+
"monaco-editor": "^0.54.0"
57+
},
58+
"peerDependenciesMeta": {
59+
"monaco-editor": {
60+
"optional": false
61+
},
62+
"@monaco-editor/react": {
63+
"optional": false
64+
}
5765
},
5866
"devDependencies": {
5967
"@octokit/rest": "^18.0.0",

packages/module/src/CodeModal/CodeModal.tsx

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,37 @@
55
import type { FunctionComponent, MouseEvent } from 'react';
66
import { useState, useEffect, useRef } from 'react';
77
import path from 'path-browserify';
8-
import * as monaco from 'monaco-editor';
9-
import { loader } from '@monaco-editor/react';
108

119
// Import PatternFly components
1210
import { CodeEditor } from '@patternfly/react-code-editor';
1311
import {
12+
Bullseye,
1413
Button,
1514
getResizeObserver,
1615
ModalBody,
1716
ModalFooter,
1817
ModalHeader,
18+
Spinner,
1919
Stack,
2020
StackItem
2121
} from '@patternfly/react-core';
2222
import FileDetails, { extensionToLanguage } from '../FileDetails';
2323
import { ChatbotDisplayMode } from '../Chatbot';
2424
import ChatbotModal from '../ChatbotModal/ChatbotModal';
2525

26-
// Configure Monaco loader to use the npm package instead of CDN
27-
loader.config({ monaco });
26+
// Try to lazy load - some consumers need to be below a certain bundle size, but can't use the CDN and don't have webpack
27+
let monacoInstance: typeof import('monaco-editor') | null = null;
28+
const loadMonaco = async () => {
29+
if (!monacoInstance) {
30+
const [monaco, { loader }] = await Promise.all([
31+
import('monaco-editor'),
32+
import('@monaco-editor/react')
33+
]);
34+
monacoInstance = monaco;
35+
loader.config({ monaco });
36+
}
37+
return monacoInstance;
38+
};
2839

2940
export interface CodeModalProps {
3041
/** Class applied to code editor */
@@ -63,6 +74,8 @@ export interface CodeModalProps {
6374
modalBodyClassName?: string;
6475
/** Class applied to modal footer */
6576
modalFooterClassName?: string;
77+
/** Aria label applied to spinner when loading Monaco */
78+
spinnerAriaLabel?: string;
6679
}
6780

6881
export const CodeModal: FunctionComponent<CodeModalProps> = ({
@@ -84,13 +97,32 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
8497
modalHeaderClassName,
8598
modalBodyClassName,
8699
modalFooterClassName,
100+
spinnerAriaLabel = 'Loading',
87101
...props
88102
}: CodeModalProps) => {
89103
const [newCode, setNewCode] = useState(code);
90-
const [editorInstance, setEditorInstance] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
104+
const [editorInstance, setEditorInstance] = useState<any>(null);
91105
const [isEditorReady, setIsEditorReady] = useState(false);
106+
const [isMonacoLoading, setIsMonacoLoading] = useState(false);
107+
const [isMonacoLoaded, setIsMonacoLoaded] = useState(false);
92108
const containerRef = useRef<HTMLDivElement>(null);
93109

110+
useEffect(() => {
111+
if (isModalOpen && !isMonacoLoaded && !isMonacoLoading) {
112+
setIsMonacoLoading(true);
113+
loadMonaco()
114+
.then(() => {
115+
setIsMonacoLoaded(true);
116+
setIsMonacoLoading(false);
117+
})
118+
.catch((error) => {
119+
// eslint-disable-next-line no-console
120+
console.error('Failed to load Monaco editor:', error);
121+
setIsMonacoLoading(false);
122+
});
123+
}
124+
}, [isModalOpen, isMonacoLoaded, isMonacoLoading]);
125+
94126
useEffect(() => {
95127
if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
96128
return;
@@ -166,27 +198,31 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
166198
<FileDetails fileName={fileName} />
167199
</StackItem>
168200
<div className="pf-v6-l-stack__item pf-chatbot__code-modal-editor" ref={containerRef}>
169-
<CodeEditor
170-
isDarkTheme
171-
isLineNumbersVisible={isLineNumbersVisible}
172-
isLanguageLabelVisible
173-
isCopyEnabled={isCopyEnabled}
174-
isReadOnly={isReadOnly}
175-
code={newCode}
176-
language={extensionToLanguage[path.extname(fileName).slice(1)]}
177-
onEditorDidMount={onEditorDidMount}
178-
onCodeChange={onCodeChange}
179-
className={codeEditorClassName}
180-
isFullHeight
181-
options={{
182-
glyphMargin: false,
183-
folding: false,
184-
// prevents Monaco from handling resizing itself
185-
// was causing ResizeObserver issues
186-
automaticLayout: false
187-
}}
188-
{...props}
189-
/>
201+
{isMonacoLoading ? (
202+
<Bullseye><Spinner aria-label={spinnerAriaLabel} /></Bullseye>
203+
) : isMonacoLoaded ? (
204+
<CodeEditor
205+
isDarkTheme
206+
isLineNumbersVisible={isLineNumbersVisible}
207+
isLanguageLabelVisible
208+
isCopyEnabled={isCopyEnabled}
209+
isReadOnly={isReadOnly}
210+
code={newCode}
211+
language={extensionToLanguage[path.extname(fileName).slice(1)]}
212+
onEditorDidMount={onEditorDidMount}
213+
onCodeChange={onCodeChange}
214+
className={codeEditorClassName}
215+
isFullHeight
216+
options={{
217+
glyphMargin: false,
218+
folding: false,
219+
// prevents Monaco from handling resizing itself
220+
// was causing ResizeObserver issues
221+
automaticLayout: false
222+
}}
223+
{...props}
224+
/>
225+
) : null}
190226
</div>
191227
</Stack>
192228
</ModalBody>

packages/module/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/* Basic Options */
66
// "incremental": true, /* Enable incremental compilation */
77
"target": "es2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */,
8-
"module": "es2015" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
8+
"module": "es2020" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
99
// "lib": [], /* Specify library files to be included in the compilation. */
1010
// "allowJs": true, /* Allow javascript files to be compiled. */
1111
// "checkJs": true, /* Report errors in .js files. */

0 commit comments

Comments
 (0)