/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import React, { forwardRef, useState, useEffect, useRef, useImperativeHandle, useCallback } from "react"; import { EuiFormRow } from "@elastic/eui"; import MonacoEditor from "react-monaco-editor"; import { monaco } from "@osd/monaco"; import { IJSONEditorRef } from "../JSONEditor"; import { MonacoJSONEditorProps } from "./interface"; import { useDiagnosticsOptions, useModel } from "./hooks"; import "./MonacoJSONEditor.scss"; const MonacoJSONEditor = forwardRef( ({ value, onChange, diagnosticsOptions, path, ...others }: MonacoJSONEditorProps, ref: React.Ref) => { const [confirmModalVisible, setConfirmModalVisible] = useState(false); const [isReady, setIsReady] = useState(false); const [editorValue, setEditorValue] = useState(value); const inputRef = useRef(null); const editorRef = useRef(undefined); const hasBindEventRef = useRef(false); useDiagnosticsOptions({ monaco, diagnosticsOptions, }); const onClickOutsideHandler = useRef(() => { if (others.disabled) { return; } try { const value = editorRef.current?.getValue(); if (!value) { throw new Error("Value can not be empty"); } JSON.parse(value); setConfirmModalVisible(false); onChange && onChange(value); } catch (e) { setConfirmModalVisible(true); } }); const setAllValue = useCallback( (val: string) => { setEditorValue(val); if (isReady) { inputRef.current?.setAttribute("value", val); if (inputRef.current) { inputRef.current.value = val; } } }, [setEditorValue, isReady, inputRef.current] ); const valueRef = useRef(editorValue); valueRef.current = editorValue; useEffect(() => { setAllValue(value); }, [value, setAllValue]); useModel({ editor: editorRef.current, path, }); useEffect(() => { editorRef.current?.getDomNode()?.setAttribute("data-test-subj", "codeEditorContainer"); if (editorRef.current && isReady && !hasBindEventRef.current) { editorRef.current.onDidBlurEditorWidget(onClickOutsideHandler.current); hasBindEventRef.current = true; } }, [isReady]); useEffect(() => { return () => { onClickOutsideHandler.current(); }; }, []); useImperativeHandle(ref, () => ({ validate: () => new Promise((resolve, reject) => { try { JSON.parse(editorRef.current?.getValue() || "{}"); resolve(""); } catch (e) { setConfirmModalVisible(true); reject("Format validate error"); } }), getValue: () => valueRef.current, setValue: (val: string) => setAllValue(val), })); return ( <>