Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0fb58e0
fix: complete monaco dependency build migration
exKAZUu Apr 18, 2026
54db575
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 18, 2026
bba6c9d
test: cover built package in next e2e
exKAZUu Apr 18, 2026
407e372
Merge remote-tracking branch 'origin/fix/complete-monaco-dependency-p…
exKAZUu Apr 18, 2026
92398e9
test: add built package contract script
exKAZUu Apr 18, 2026
6627eb3
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 18, 2026
b1ee6bc
test: build package only when needed
exKAZUu Apr 18, 2026
efb2135
Merge remote-tracking branch 'origin/fix/complete-monaco-dependency-p…
exKAZUu Apr 18, 2026
8ece636
docs: clarify monaco editor dependency
exKAZUu Apr 18, 2026
644686a
chore: remove standard typescript dependency
exKAZUu Apr 18, 2026
4e77465
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 18, 2026
b6714a5
build: enable library minification
exKAZUu Apr 18, 2026
83dae33
Merge remote-tracking branch 'origin/fix/complete-monaco-dependency-p…
exKAZUu Apr 18, 2026
e611c9e
build: run package build only for next e2e
exKAZUu Apr 18, 2026
7a829c5
.
exKAZUu Apr 18, 2026
c3a4a73
.
exKAZUu Apr 18, 2026
9e0604c
fix: resolve lint warnings
exKAZUu Apr 18, 2026
a1929c7
.
exKAZUu Apr 18, 2026
2aff6e0
fix: resolve clean lint in e2e fixture
exKAZUu Apr 18, 2026
81a1064
fix: use local build command in package script
exKAZUu Apr 18, 2026
c637e13
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 18, 2026
604374a
fix: stabilize package export e2e assertion
exKAZUu Apr 18, 2026
2cb6259
Merge remote-tracking branch 'origin/fix/complete-monaco-dependency-p…
exKAZUu Apr 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/monaco-react.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ This package is a maintained fork of [`suren-atoyan/monaco-react`](https://githu
## Installation

```bash
yarn add @willbooster/monaco-react monaco-editor
yarn add @willbooster/monaco-react
```

`react`, `react-dom`, and `monaco-editor` are peer dependencies. This package supports React 19.x, Node.js 24 or newer, and is tested with Next.js 16.
`react` and `react-dom` are peer dependencies. `monaco-editor` is a direct dependency for Monaco type resolution. This package supports React 19.x, Node.js 24 or newer, and is tested with Next.js 16.

## Usage

Expand Down
8 changes: 5 additions & 3 deletions e2e/next-app/app/editorProbe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import { useState } from 'react';

import Editor, { DiffEditor, loader, useMonaco, type Monaco } from '@willbooster/monaco-react';
import MonacoEditor, { DiffEditor, loader, useMonaco, type Monaco } from '@willbooster/monaco-react';

type LoaderConfig = Parameters<typeof loader.config>[0];

const model = {
uri: { path: '/e2e.ts' },
Expand Down Expand Up @@ -53,7 +55,7 @@ const monaco = {
},
} as unknown as Monaco;

loader.config({ monaco });
loader.config({ monaco: monaco as LoaderConfig['monaco'] });

export default function EditorProbe() {
const [editorStatus, setEditorStatus] = useState('editor-pending');
Expand All @@ -64,7 +66,7 @@ export default function EditorProbe() {
<>
<p data-testid="hook-status">{loadedMonaco === monaco ? 'hook-ok' : 'hook-pending'}</p>
<div data-testid="editor-status">{editorStatus}</div>
<Editor
<MonacoEditor
height={120}
defaultValue="const answer = 42;"
defaultLanguage="typescript"
Expand Down
44 changes: 0 additions & 44 deletions e2e/next-app/monaco-react.d.ts

This file was deleted.

12 changes: 12 additions & 0 deletions e2e/next-app/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
import { existsSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const appDir = path.dirname(fileURLToPath(import.meta.url));
const packageRoot = path.resolve(appDir, '../..');
const builtEntry = path.join(packageRoot, 'dist/index.js');

if (!existsSync(builtEntry)) {
throw new Error('Run `yarn build` before building the Next.js e2e fixture.');
}

/** @type {import('next').NextConfig} */
const nextConfig = {};

Expand Down
27 changes: 27 additions & 0 deletions e2e/next-app/next.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

import { expect, test } from '@playwright/test';

const testFile = fileURLToPath(import.meta.url);
const appDir = path.dirname(testFile);
const packageRoot = path.resolve(appDir, '../..');

test('resolves monaco-react from the built package files', async () => {
const packageJson = JSON.parse(await readFile(path.join(packageRoot, 'package.json'), 'utf8')) as {
exports: { '.': { import: string; require: string; types: string } };
};

expect(packageJson.exports['.']).toEqual({
import: './dist/index.js',
require: './dist/index.cjs',
types: './dist/index.d.ts',
});
await expect(readFile(path.join(packageRoot, packageJson.exports['.'].require), 'utf8')).resolves.toContain(
'"use strict"'
);
await expect(readFile(path.join(packageRoot, 'dist/index.js'), 'utf8')).resolves.toMatch(/^"use client";/);
await expect(readFile(path.join(packageRoot, 'dist/index.d.ts'), 'utf8')).resolves.toContain(
"from 'monaco-editor/esm/vs/editor/editor.api.js'"
);
});

test('loads monaco-react through the Next.js app router', async ({ page }) => {
const errors: string[] = [];
page.on('console', (message) => {
Expand Down
3 changes: 3 additions & 0 deletions e2e/next-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"name": "next"
}
],
"paths": {
"@willbooster/monaco-react": ["../../dist/index.d.ts", "../../src/index.ts"]
},
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@
"access": "public"
},
"scripts": {
"build": "tsup",
"build": "yarn run build/core",
"build/core": "build-ts lib",
"check-all-for-ai": "yarn check-for-ai && yarn test",
"check-for-ai": "yarn install > /dev/null && yarn format > /dev/null 2> /dev/null || true && yarn lint-fix --quiet",
"cleanup": "yarn format && yarn lint-fix",
"common/ci-setup": "yarn run build/core",
"format": "sort-package-json && yarn format-code",
"format-code": "oxfmt --write --no-error-on-unmatched-pattern .",
"lint": "oxlint --no-error-on-unmatched-pattern .",
Expand Down Expand Up @@ -70,6 +72,7 @@
"@typescript/native-preview": "7.0.0-dev.20260418.1",
"@willbooster/oxfmt-config": "1.2.1",
"@willbooster/oxlint-config": "1.4.4",
"build-ts": "17.1.5",
"conventional-changelog-conventionalcommits": "9.3.1",
"jsdom": "29.0.2",
"lefthook": "2.1.5",
Expand All @@ -81,8 +84,6 @@
"react-dom": "19.2.5",
"semantic-release": "25.0.3",
"sort-package-json": "3.6.1",
"tsup": "8.5.0",
"typescript": "5.9.3",
"vitest": "4.1.4"
},
"peerDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions src/DiffEditor/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { editor } from 'monaco-editor/esm/vs/editor/editor.api.js';
import type { ReactNode } from 'react';
import type { Monaco, Theme } from '..';
import type { Monaco } from '..';

export type MonacoDiffEditor = editor.IStandaloneDiffEditor;

Expand Down Expand Up @@ -68,7 +68,7 @@ export interface DiffEditorProps {
* Define new themes by `monaco.editor.defineTheme`
* @default "light"
*/
theme?: Theme | string;
theme?: string;

/**
* The loading screen before the editor will be mounted
Expand Down
16 changes: 11 additions & 5 deletions src/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function Editor({
const [isEditorReady, setIsEditorReady] = useState(false);
const [isMonacoMounting, setIsMonacoMounting] = useState(true);
const monacoRef = useRef<Monaco | null>(null);
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
const editorRef = useRef<editor.IStandaloneCodeEditor | undefined>(undefined);
const containerRef = useRef<HTMLDivElement | null>(null);
const onMountRef = useRef(onMount);
const beforeMountRef = useRef(beforeMount);
Expand Down Expand Up @@ -167,7 +167,9 @@ function Editor({
);
editorRef.current = editor;

saveViewState && editor.restoreViewState(viewStates.get(autoCreatedModelPath));
if (saveViewState) {
editor.restoreViewState(viewStates.get(autoCreatedModelPath));
}

monacoRef.current.editor.setTheme(theme);

Expand Down Expand Up @@ -199,7 +201,9 @@ function Editor({
}, [isEditorReady]);

useEffect(() => {
!isMonacoMounting && !isEditorReady && createEditor();
if (!isMonacoMounting && !isEditorReady) {
createEditor();
}
}, [isMonacoMounting, isEditorReady, createEditor]);

// subscription
Expand Down Expand Up @@ -248,14 +252,16 @@ function Editor({
subscriptionRef.current?.dispose();

if (keepCurrentModel) {
saveViewState && viewStates.set(path, editorRef.current!.saveViewState());
if (saveViewState) {
viewStates.set(path, editorRef.current!.saveViewState());
}
} else {
editorRef.current!.getModel()?.dispose();
}

editorRef.current!.dispose();

editorRef.current = null;
editorRef.current = undefined;
preventCreation.current = false;
setIsEditorReady(false);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Editor/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { editor } from 'monaco-editor/esm/vs/editor/editor.api.js';
import type { Monaco, Theme } from '..';
import type { Monaco } from '..';
import type { ReactNode } from 'react';

export type OnMount = (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => void;
Expand Down Expand Up @@ -51,7 +51,7 @@ export interface EditorProps {
* Define new themes by `monaco.editor.defineTheme`
* @default "light"
*/
theme?: Theme | string;
theme?: string;

/**
* The line to jump on it
Expand Down
6 changes: 4 additions & 2 deletions src/hooks/useMount/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';
import type { EffectCallback } from 'react';

function useMount(effect: EffectCallback): void {
useEffect(effect, []);
const effectRef = useRef(effect);

useEffect(() => effectRef.current(), []);
}

export default useMount;
Loading
Loading