or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

diff-editor.mdeditor.mdindex.mdloader.mdmonaco-hook.md

monaco-hook.mddocs/

0

# Monaco Hook

1

2

React hook for accessing the Monaco Editor instance and its APIs across components without needing to pass instances through props.

3

4

## Capabilities

5

6

### useMonaco Hook

7

8

React hook that provides access to the Monaco Editor instance once it's loaded.

9

10

```typescript { .api }

11

/**

12

* React hook for accessing the Monaco Editor instance

13

* @returns Monaco instance or null if not yet loaded

14

*/

15

function useMonaco(): Monaco | null;

16

17

type Monaco = typeof monaco;

18

```

19

20

**Usage Examples:**

21

22

```typescript

23

import React, { useEffect } from "react";

24

import { useMonaco } from "@monaco-editor/react";

25

26

// Basic Monaco instance access

27

function MonacoStatus() {

28

const monaco = useMonaco();

29

30

useEffect(() => {

31

if (monaco) {

32

console.log("Monaco Editor is ready!");

33

console.log("Available languages:", monaco.languages.getLanguages());

34

}

35

}, [monaco]);

36

37

return (

38

<div>

39

Monaco Status: {monaco ? "Loaded" : "Loading..."}

40

</div>

41

);

42

}

43

44

// Custom language configuration

45

function CustomLanguageSetup() {

46

const monaco = useMonaco();

47

48

useEffect(() => {

49

if (!monaco) return;

50

51

// Register custom language

52

monaco.languages.register({ id: 'myLang' });

53

54

// Define language syntax

55

monaco.languages.setMonarchTokensProvider('myLang', {

56

tokenizer: {

57

root: [

58

[/\[error.*/, "custom-error"],

59

[/\[notice.*/, "custom-notice"],

60

[/\[info.*/, "custom-info"],

61

[/\[[a-zA-Z 0-9:]+\]/, "custom-date"],

62

]

63

}

64

});

65

66

// Configure language features

67

monaco.languages.setLanguageConfiguration('myLang', {

68

brackets: [

69

['[', ']'],

70

['(', ')'],

71

['{', '}']

72

],

73

autoClosingPairs: [

74

{ open: '[', close: ']' },

75

{ open: '(', close: ')' },

76

{ open: '{', close: '}' },

77

]

78

});

79

80

}, [monaco]);

81

82

return <div>Custom language configured</div>;

83

}

84

```

85

86

### Theme Management

87

88

Use the Monaco instance to define and manage custom themes across your application.

89

90

```typescript { .api }

91

// Theme definition interface (from Monaco Editor)

92

interface ThemeDefinition {

93

base: 'vs' | 'vs-dark' | 'hc-black';

94

inherit: boolean;

95

rules: TokenThemeRule[];

96

colors: { [colorId: string]: string };

97

}

98

99

interface TokenThemeRule {

100

token: string;

101

foreground?: string;

102

background?: string;

103

fontStyle?: string;

104

}

105

```

106

107

**Theme Examples:**

108

109

```typescript

110

import React, { useEffect } from "react";

111

import { useMonaco } from "@monaco-editor/react";

112

113

function ThemeManager() {

114

const monaco = useMonaco();

115

116

useEffect(() => {

117

if (!monaco) return;

118

119

// Define custom dark theme

120

monaco.editor.defineTheme('customDark', {

121

base: 'vs-dark',

122

inherit: true,

123

rules: [

124

{ token: 'comment', foreground: '6A9955', fontStyle: 'italic' },

125

{ token: 'keyword', foreground: '569CD6', fontStyle: 'bold' },

126

{ token: 'string', foreground: 'CE9178' },

127

{ token: 'number', foreground: 'B5CEA8' },

128

],

129

colors: {

130

'editor.background': '#1e1e1e',

131

'editor.foreground': '#d4d4d4',

132

'editorLineNumber.foreground': '#858585',

133

'editorCursor.foreground': '#ffffff',

134

'editor.selectionBackground': '#264f78',

135

'editor.lineHighlightBackground': '#2d2d30',

136

}

137

});

138

139

// Define custom light theme

140

monaco.editor.defineTheme('customLight', {

141

base: 'vs',

142

inherit: true,

143

rules: [

144

{ token: 'comment', foreground: '008000', fontStyle: 'italic' },

145

{ token: 'keyword', foreground: '0000ff', fontStyle: 'bold' },

146

{ token: 'string', foreground: 'a31515' },

147

{ token: 'number', foreground: '098658' },

148

],

149

colors: {

150

'editor.background': '#ffffff',

151

'editor.foreground': '#000000',

152

'editorLineNumber.foreground': '#237893',

153

'editor.selectionBackground': '#add6ff',

154

'editor.lineHighlightBackground': '#f0f0f0',

155

}

156

});

157

158

}, [monaco]);

159

160

const applyTheme = (themeName) => {

161

if (monaco) {

162

monaco.editor.setTheme(themeName);

163

}

164

};

165

166

return (

167

<div>

168

<button onClick={() => applyTheme('customDark')}>Dark Theme</button>

169

<button onClick={() => applyTheme('customLight')}>Light Theme</button>

170

<button onClick={() => applyTheme('vs-dark')}>VS Dark</button>

171

<button onClick={() => applyTheme('vs')}>VS Light</button>

172

</div>

173

);

174

}

175

```

176

177

### Language Service Configuration

178

179

Configure TypeScript/JavaScript language services and other language features.

180

181

```typescript { .api }

182

// Language service configuration interfaces (from Monaco Editor)

183

interface LanguageServiceDefaults {

184

setCompilerOptions(options: CompilerOptions): void;

185

setDiagnosticsOptions(options: DiagnosticsOptions): void;

186

addExtraLib(content: string, filePath?: string): void;

187

setEagerModelSync(value: boolean): void;

188

}

189

```

190

191

**Language Service Examples:**

192

193

```typescript

194

import React, { useEffect } from "react";

195

import { useMonaco } from "@monaco-editor/react";

196

197

function TypeScriptConfiguration() {

198

const monaco = useMonaco();

199

200

useEffect(() => {

201

if (!monaco) return;

202

203

// Configure TypeScript compiler options

204

monaco.languages.typescript.typescriptDefaults.setCompilerOptions({

205

target: monaco.languages.typescript.ScriptTarget.ES2020,

206

allowNonTsExtensions: true,

207

moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,

208

module: monaco.languages.typescript.ModuleKind.CommonJS,

209

noEmit: true,

210

esModuleInterop: true,

211

jsx: monaco.languages.typescript.JsxEmit.React,

212

reactNamespace: "React",

213

allowJs: true,

214

typeRoots: ["node_modules/@types"]

215

});

216

217

// Configure diagnostics

218

monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({

219

noSemanticValidation: false,

220

noSyntaxValidation: false,

221

noSuggestionDiagnostics: false

222

});

223

224

// Add type definitions

225

const reactTypes = `

226

declare module "react" {

227

export interface FC<P = {}> {

228

(props: P & { children?: ReactNode }): ReactElement | null;

229

}

230

export type ReactNode = ReactElement | string | number | boolean | null | undefined;

231

export interface ReactElement<P = any> {

232

type: string | FC<P>;

233

props: P;

234

key: string | number | null;

235

}

236

}

237

`;

238

239

monaco.languages.typescript.typescriptDefaults.addExtraLib(

240

reactTypes,

241

'file:///node_modules/@types/react/index.d.ts'

242

);

243

244

// Enable eager model sync for better performance

245

monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);

246

247

}, [monaco]);

248

249

return <div>TypeScript language service configured</div>;

250

}

251

252

function CustomCompletionProvider() {

253

const monaco = useMonaco();

254

255

useEffect(() => {

256

if (!monaco) return;

257

258

// Register custom completion provider

259

const disposable = monaco.languages.registerCompletionItemProvider('javascript', {

260

provideCompletionItems: (model, position) => {

261

const suggestions = [

262

{

263

label: 'console.log',

264

kind: monaco.languages.CompletionItemKind.Function,

265

documentation: 'Log a message to the console',

266

insertText: 'console.log($1);',

267

insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,

268

range: {

269

startLineNumber: position.lineNumber,

270

endLineNumber: position.lineNumber,

271

startColumn: position.column,

272

endColumn: position.column

273

}

274

},

275

{

276

label: 'async function',

277

kind: monaco.languages.CompletionItemKind.Snippet,

278

documentation: 'Create an async function',

279

insertText: 'async function ${1:functionName}(${2:params}) {\n\t$0\n}',

280

insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,

281

range: {

282

startLineNumber: position.lineNumber,

283

endLineNumber: position.lineNumber,

284

startColumn: position.column,

285

endColumn: position.column

286

}

287

}

288

];

289

290

return { suggestions };

291

}

292

});

293

294

// Cleanup on unmount

295

return () => disposable.dispose();

296

}, [monaco]);

297

298

return <div>Custom completion provider registered</div>;

299

}

300

```

301

302

### Global Monaco Configuration

303

304

Configure Monaco Editor settings that apply to all editor instances.

305

306

```typescript { .api }

307

// Global configuration options

308

interface GlobalMonacoConfig {

309

/** Configure default options for all editors */

310

setGlobalOptions(options: editor.IEditorOptions): void;

311

/** Register global commands */

312

addGlobalCommand(keybinding: number, handler: () => void): void;

313

/** Configure language features globally */

314

configureLanguageGlobally(languageId: string, config: any): void;

315

}

316

```

317

318

**Global Configuration Examples:**

319

320

```typescript

321

import React, { useEffect } from "react";

322

import { useMonaco } from "@monaco-editor/react";

323

324

function GlobalMonacoSetup() {

325

const monaco = useMonaco();

326

327

useEffect(() => {

328

if (!monaco) return;

329

330

// Set global editor defaults

331

monaco.editor.EditorOptions.fontSize.defaultValue = 14;

332

monaco.editor.EditorOptions.fontFamily.defaultValue = 'Monaco, Menlo, monospace';

333

monaco.editor.EditorOptions.lineHeight.defaultValue = 1.6;

334

335

// Configure global key bindings

336

const formatAction = {

337

id: 'format-document',

338

label: 'Format Document',

339

keybindings: [monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.KeyF],

340

run: (editor) => {

341

editor.getAction('editor.action.formatDocument').run();

342

}

343

};

344

345

// Register global actions

346

monaco.editor.addEditorAction(formatAction);

347

348

// Configure language defaults

349

const jsDefaults = monaco.languages.typescript.javascriptDefaults;

350

jsDefaults.setCompilerOptions({

351

allowNonTsExtensions: true,

352

allowJs: true

353

});

354

355

}, [monaco]);

356

357

return <div>Global Monaco configuration applied</div>;

358

}

359

```

360

361

## Integration Patterns

362

363

### Provider Pattern

364

365

Create a Monaco context provider for app-wide access.

366

367

```typescript

368

import React, { createContext, useContext, useEffect, useState } from "react";

369

import { useMonaco } from "@monaco-editor/react";

370

371

const MonacoContext = createContext(null);

372

373

export function MonacoProvider({ children }) {

374

const monaco = useMonaco();

375

const [isConfigured, setIsConfigured] = useState(false);

376

377

useEffect(() => {

378

if (!monaco || isConfigured) return;

379

380

// Apply global configuration

381

monaco.editor.defineTheme('appTheme', {

382

base: 'vs-dark',

383

inherit: true,

384

rules: [],

385

colors: {

386

'editor.background': '#1a1a1a',

387

}

388

});

389

390

setIsConfigured(true);

391

}, [monaco, isConfigured]);

392

393

return (

394

<MonacoContext.Provider value={{ monaco, isConfigured }}>

395

{children}

396

</MonacoContext.Provider>

397

);

398

}

399

400

export function useAppMonaco() {

401

const context = useContext(MonacoContext);

402

if (!context) {

403

throw new Error('useAppMonaco must be used within MonacoProvider');

404

}

405

return context;

406

}

407

```

408

409

### Conditional Rendering

410

411

Only render Monaco-dependent components after Monaco is loaded.

412

413

```typescript

414

import React from "react";

415

import { useMonaco } from "@monaco-editor/react";

416

import Editor from "@monaco-editor/react";

417

418

function ConditionalEditor() {

419

const monaco = useMonaco();

420

421

if (!monaco) {

422

return <div>Loading Monaco Editor...</div>;

423

}

424

425

return (

426

<div>

427

<Editor

428

height="400px"

429

language="javascript"

430

defaultValue="// Monaco is ready!"

431

/>

432

</div>

433

);

434

}

435

```