Skip to content

Commit 68a5f5c

Browse files
authored
feat(ui): expose onMount to CodeField (#10223)
This is useful for modifying the monaco instance, e.g. to add external types to the editor: ```tsx <CodeField autoComplete={autoComplete} field={props} forceRender={forceRender} key={key} onMount={(editor, monaco) => { console.log('editor mounted') monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ allowNonTsExtensions: true, moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs, paths: { payload: ['file:///node_modules/payload/index.d.ts'], }, target: monaco.languages.typescript.ScriptTarget.ESNext, typeRoots: ['node_modules/@types', 'node_modules/payload'], }) const run = async () => { const types = await fetch('https://unpkg.com/payload@latest/dist/index.d.ts') const typesText = await types.text() monaco.languages.typescript.typescriptDefaults.addExtraLib( typesText, 'file:///node_modules/payload/index.d.ts', ) } void run() }} path={path} permissions={permissions} readOnly={readOnly} renderedBlocks={renderedBlocks} schemaPath={schemaPath} validate={validate} /> ```
1 parent fabe541 commit 68a5f5c

File tree

3 files changed

+83
-6
lines changed

3 files changed

+83
-6
lines changed

packages/payload/src/admin/fields/Code.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { EditorProps } from '@monaco-editor/react'
12
import type { MarkOptional } from 'ts-essentials'
23

34
import type { CodeField, CodeFieldClient } from '../../fields/config/types.js'
@@ -20,6 +21,7 @@ type CodeFieldClientWithoutType = MarkOptional<CodeFieldClient, 'type'>
2021

2122
type CodeFieldBaseClientProps = {
2223
readonly autoComplete?: string
24+
readonly onMount?: EditorProps['onMount']
2325
readonly path: string
2426
readonly validate?: CodeFieldValidation
2527
}

packages/ui/src/fields/Code/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const CodeFieldComponent: CodeFieldClientComponent = (props) => {
3030
localized,
3131
required,
3232
},
33+
onMount,
3334
path,
3435
readOnly,
3536
validate,
@@ -84,6 +85,7 @@ const CodeFieldComponent: CodeFieldClientComponent = (props) => {
8485
<CodeEditor
8586
defaultLanguage={prismToMonacoLanguageMap[language] || language}
8687
onChange={readOnly ? () => null : (val) => setValue(val)}
88+
onMount={onMount}
8789
options={editorOptions}
8890
readOnly={readOnly}
8991
value={(value as string) || ''}

test/lexical-mdx/collections/Posts/CodeFields.tsx

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import type { CodeFieldClientProps } from 'payload'
3+
import type { CodeFieldClient, CodeFieldClientProps } from 'payload'
44

55
import { CodeField, useFormFields } from '@payloadcms/ui'
66
import React, { useMemo } from 'react'
@@ -13,21 +13,57 @@ const languageKeyToMonacoLanguageMap = {
1313
tsx: 'typescript',
1414
}
1515

16-
export const Code: React.FC<CodeFieldClientProps> = ({ field }) => {
16+
export const Code: React.FC<CodeFieldClientProps> = ({
17+
autoComplete,
18+
field,
19+
forceRender,
20+
path,
21+
permissions,
22+
readOnly,
23+
renderedBlocks,
24+
schemaPath,
25+
validate,
26+
}) => {
1727
const languageField = useFormFields(([fields]) => fields['language'])
1828

1929
const language: string =
2030
(languageField?.value as string) || (languageField.initialValue as string) || 'typescript'
2131

2232
const label = languages[language as keyof typeof languages]
2333

24-
const props: typeof field = useMemo(
34+
const props: CodeFieldClient = useMemo<CodeFieldClient>(
2535
() => ({
2636
...field,
37+
type: 'code',
2738
admin: {
2839
...field.admin,
29-
components: field.admin?.components || {},
30-
editorOptions: field.admin?.editorOptions || {},
40+
description: 'test',
41+
editorOptions: {
42+
onMount: (editor, monaco) => {
43+
// Set module resolution to NodeNext to enable autocompletion
44+
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
45+
allowNonTsExtensions: true,
46+
module: monaco.languages.typescript.ModuleKind.ESNext,
47+
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
48+
target: monaco.languages.typescript.ScriptTarget.ESNext,
49+
typeRoots: ['node_modules/@types'],
50+
})
51+
52+
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
53+
noSemanticValidation: false,
54+
noSyntaxValidation: false,
55+
})
56+
57+
const libUri = 'node_modules/@types/payload/index.d.ts'
58+
59+
const run = async () => {
60+
const types = await fetch('https://unpkg.com/payload@latest/dist/index.d.ts')
61+
const libSource = await types.text()
62+
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, libUri)
63+
}
64+
void run()
65+
},
66+
} as any,
3167
label,
3268
language: languageKeyToMonacoLanguageMap[language] || language,
3369
},
@@ -37,5 +73,42 @@ export const Code: React.FC<CodeFieldClientProps> = ({ field }) => {
3773

3874
const key = `${field.name}-${language}-${label}`
3975

40-
return <CodeField field={props} key={key} />
76+
return (
77+
props && (
78+
<CodeField
79+
autoComplete={autoComplete}
80+
field={props}
81+
forceRender={forceRender}
82+
key={key}
83+
onMount={(editor, monaco) => {
84+
console.log('editor mounted')
85+
// Set module resolution to NodeNext to enable autocompletion
86+
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
87+
allowNonTsExtensions: true,
88+
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
89+
paths: {
90+
payload: ['file:///node_modules/payload/index.d.ts'],
91+
},
92+
target: monaco.languages.typescript.ScriptTarget.ESNext,
93+
typeRoots: ['node_modules/@types', 'node_modules/payload'],
94+
})
95+
const run = async () => {
96+
const types = await fetch('https://unpkg.com/payload@latest/dist/index.d.ts')
97+
const typesText = await types.text()
98+
monaco.languages.typescript.typescriptDefaults.addExtraLib(
99+
typesText,
100+
'file:///node_modules/payload/index.d.ts',
101+
)
102+
}
103+
void run()
104+
}}
105+
path={path}
106+
permissions={permissions}
107+
readOnly={readOnly}
108+
renderedBlocks={renderedBlocks}
109+
schemaPath={schemaPath}
110+
validate={validate}
111+
/>
112+
)
113+
)
41114
}

0 commit comments

Comments
 (0)