import { defaultKeymap } from '@codemirror/commands'; import { Compartment, EditorState } from '@codemirror/state'; import { keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view'; import classnames from 'classnames'; import { EditorView } from 'codemirror'; import { formatSdl } from 'format-graphql'; import { useEffect, useRef } from 'react'; import { useUnmount } from 'react-use'; import { IconButton } from '../IconButton'; import './Editor.css'; import { baseExtensions, getLanguageExtension, multiLineExtensions } from './extensions'; import { singleLineExt } from './singleLine'; export interface _EditorProps { id?: string; readOnly?: boolean; className?: string; heightMode?: 'auto' | 'full'; contentType?: string; autoFocus?: boolean; defaultValue?: string; placeholder?: string; tooltipContainer?: HTMLElement; useTemplating?: boolean; onChange?: (value: string) => void; singleLine?: boolean; } export function _Editor({ readOnly, heightMode, contentType, autoFocus, placeholder, useTemplating, defaultValue, onChange, className, singleLine, }: _EditorProps) { const cm = useRef<{ view: EditorView; langHolder: Compartment } | null>(null); // Unmount the editor useUnmount(() => { cm.current?.view.destroy(); cm.current = null; }); // Update language extension when contentType changes useEffect(() => { if (cm.current === null) return; const { view, langHolder } = cm.current; const ext = getLanguageExtension({ contentType, useTemplating }); view.dispatch({ effects: langHolder.reconfigure(ext) }); }, [contentType]); // Initialize the editor const initDivRef = (el: HTMLDivElement | null) => { if (el === null || cm.current !== null) return; try { const langHolder = new Compartment(); const langExt = getLanguageExtension({ contentType, useTemplating }); const state = EditorState.create({ doc: `${defaultValue ?? ''}`, extensions: [ langHolder.of(langExt), ...getExtensions({ container: el, readOnly, placeholder, singleLine, onChange, contentType, useTemplating, }), ], }); const view = new EditorView({ state, parent: el }); cm.current = { view, langHolder }; syncGutterBg({ parent: el, className }); if (autoFocus) view.focus(); } catch (e) { console.log('Failed to initialize Codemirror', e); } }; return (