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}
/>
```
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import type { EditorProps } from '@monaco-editor/react'
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { CodeField, CodeFieldClient } from '../../fields/config/types.js'
|
||||
@@ -20,6 +21,7 @@ type CodeFieldClientWithoutType = MarkOptional<CodeFieldClient, 'type'>
|
||||
|
||||
type CodeFieldBaseClientProps = {
|
||||
readonly autoComplete?: string
|
||||
readonly onMount?: EditorProps['onMount']
|
||||
readonly path: string
|
||||
readonly validate?: CodeFieldValidation
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ const CodeFieldComponent: CodeFieldClientComponent = (props) => {
|
||||
localized,
|
||||
required,
|
||||
},
|
||||
onMount,
|
||||
path,
|
||||
readOnly,
|
||||
validate,
|
||||
@@ -84,6 +85,7 @@ const CodeFieldComponent: CodeFieldClientComponent = (props) => {
|
||||
<CodeEditor
|
||||
defaultLanguage={prismToMonacoLanguageMap[language] || language}
|
||||
onChange={readOnly ? () => null : (val) => setValue(val)}
|
||||
onMount={onMount}
|
||||
options={editorOptions}
|
||||
readOnly={readOnly}
|
||||
value={(value as string) || ''}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { CodeFieldClientProps } from 'payload'
|
||||
import type { CodeFieldClient, CodeFieldClientProps } from 'payload'
|
||||
|
||||
import { CodeField, useFormFields } from '@payloadcms/ui'
|
||||
import React, { useMemo } from 'react'
|
||||
@@ -13,7 +13,17 @@ const languageKeyToMonacoLanguageMap = {
|
||||
tsx: 'typescript',
|
||||
}
|
||||
|
||||
export const Code: React.FC<CodeFieldClientProps> = ({ field }) => {
|
||||
export const Code: React.FC<CodeFieldClientProps> = ({
|
||||
autoComplete,
|
||||
field,
|
||||
forceRender,
|
||||
path,
|
||||
permissions,
|
||||
readOnly,
|
||||
renderedBlocks,
|
||||
schemaPath,
|
||||
validate,
|
||||
}) => {
|
||||
const languageField = useFormFields(([fields]) => fields['language'])
|
||||
|
||||
const language: string =
|
||||
@@ -21,13 +31,39 @@ export const Code: React.FC<CodeFieldClientProps> = ({ field }) => {
|
||||
|
||||
const label = languages[language as keyof typeof languages]
|
||||
|
||||
const props: typeof field = useMemo(
|
||||
const props: CodeFieldClient = useMemo<CodeFieldClient>(
|
||||
() => ({
|
||||
...field,
|
||||
type: 'code',
|
||||
admin: {
|
||||
...field.admin,
|
||||
components: field.admin?.components || {},
|
||||
editorOptions: field.admin?.editorOptions || {},
|
||||
description: 'test',
|
||||
editorOptions: {
|
||||
onMount: (editor, monaco) => {
|
||||
// Set module resolution to NodeNext to enable autocompletion
|
||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
||||
allowNonTsExtensions: true,
|
||||
module: monaco.languages.typescript.ModuleKind.ESNext,
|
||||
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
|
||||
target: monaco.languages.typescript.ScriptTarget.ESNext,
|
||||
typeRoots: ['node_modules/@types'],
|
||||
})
|
||||
|
||||
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: false,
|
||||
noSyntaxValidation: false,
|
||||
})
|
||||
|
||||
const libUri = 'node_modules/@types/payload/index.d.ts'
|
||||
|
||||
const run = async () => {
|
||||
const types = await fetch('https://unpkg.com/payload@latest/dist/index.d.ts')
|
||||
const libSource = await types.text()
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, libUri)
|
||||
}
|
||||
void run()
|
||||
},
|
||||
} as any,
|
||||
label,
|
||||
language: languageKeyToMonacoLanguageMap[language] || language,
|
||||
},
|
||||
@@ -37,5 +73,42 @@ export const Code: React.FC<CodeFieldClientProps> = ({ field }) => {
|
||||
|
||||
const key = `${field.name}-${language}-${label}`
|
||||
|
||||
return <CodeField field={props} key={key} />
|
||||
return (
|
||||
props && (
|
||||
<CodeField
|
||||
autoComplete={autoComplete}
|
||||
field={props}
|
||||
forceRender={forceRender}
|
||||
key={key}
|
||||
onMount={(editor, monaco) => {
|
||||
console.log('editor mounted')
|
||||
// Set module resolution to NodeNext to enable autocompletion
|
||||
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}
|
||||
/>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user