import CodeMirror from '@uiw/react-codemirror'; import { useCallback, useState } from 'react'; import { createTheme } from '@uiw/codemirror-themes'; import { tags as highlightTags } from '@lezer/highlight'; import type { JSONSchema7 } from 'json-schema'; import clsx from 'clsx'; import { AutomationTestingProps } from '@/types'; import { CopyButton } from '@@/buttons/CopyButton'; import { useDebounce } from '../../hooks/useDebounce'; import { TextTip } from '../Tip/TextTip'; import { StackVersionSelector } from '../StackVersionSelector'; import styles from './CodeEditor.module.css'; import { useCodeEditorExtensions, CodeEditorType, } from './useCodeEditorExtensions'; import { FileNameHeader, FileNameHeaderRow } from './FileNameHeader'; interface Props extends AutomationTestingProps { id: string; textTip?: string; type?: CodeEditorType; readonly?: boolean; onChange?: (value: string) => void; value: string; height?: string; versions?: number[]; onVersionChange?: (version: number) => void; schema?: JSONSchema7; fileName?: string; placeholder?: string; } export const theme = createTheme({ theme: 'light', settings: { background: 'var(--bg-codemirror-color)', foreground: 'var(--text-codemirror-color)', caret: 'var(--border-codemirror-cursor-color)', selection: 'var(--bg-codemirror-selected-color)', selectionMatch: 'var(--bg-codemirror-selected-color)', }, styles: [ { tag: highlightTags.atom, color: 'var(--text-cm-default-color)' }, { tag: highlightTags.meta, color: 'var(--text-cm-meta-color)' }, { tag: [highlightTags.string, highlightTags.special(highlightTags.brace)], color: 'var(--text-cm-string-color)', }, { tag: highlightTags.number, color: 'var(--text-cm-number-color)' }, { tag: highlightTags.keyword, color: 'var(--text-cm-keyword-color)' }, { tag: highlightTags.comment, color: 'var(--text-cm-comment-color)' }, { tag: highlightTags.variableName, color: 'var(--text-cm-variable-name-color)', }, ], }); export function CodeEditor({ id, onChange = () => {}, textTip, readonly, value, versions, onVersionChange, height = '500px', type, schema, 'data-cy': dataCy, fileName, placeholder, }: Props) { const [isRollback, setIsRollback] = useState(false); const extensions = useCodeEditorExtensions(type, schema); const handleVersionChange = useCallback( (version: number) => { if (versions && versions.length > 1) { setIsRollback(version < versions[0]); } onVersionChange?.(version); }, [onVersionChange, versions] ); const [debouncedValue, debouncedOnChange] = useDebounce(value, onChange); return ( <>