import { useEffect , useState , useRef , useCallback } from 'react' ; import { i18n } from '@osd/i18n' ; import { isJSON } from '../../../static/validators/string' ; export interface JsonEditorState < T = { [ key ] : any ; } > { data : { raw : string ; format ( ) : T ; } ; validate ( ) : boolean ; isValid : boolean | undefined ; } export type OnJsonEditorUpdateHandler < T = { [ key ] : any ; } > = ( arg : JsonEditorState < T > ) => void ; interface Parameters < T extends object > { onUpdate : OnJsonEditorUpdateHandler < T > ; defaultValue ? : T ; value ? : string ; } const stringifyJson = ( json ) => Object . keys ( json ) . length ? JSON . stringify ( json , null , 2 ) : '{\n\n}' ; export const useJson = < T extends object = { [ key ] : any ; } > ( { defaultValue = { } as T , onUpdate , value , } ) => { const isControlled = value !== undefined ; const isMounted = useRef ( false ) ; const [ content , setContent ] = useState < string > ( isControlled ? value ! : stringifyJson ( defaultValue ) ) ; const [ error , setError ] = useState < string | null > ( null ) ; const validate = useCallback ( ( ) => { const isValid = content . trim ( ) === '' ? true : isJSON ( content ) ; if ( ! isValid ) { setError ( i18n . translate ( 'opensearchUi.validation.string.invalidJSONError' , { defaultMessage : 'Invalid JSON' , } ) ) ; } else { setError ( null ) ; } return isValid ; } , [ content ] ) ; const formatContent = useCallback ( ( ) => { const isValid = validate ( ) ; const data = isValid && content . trim ( ) !== '' ? JSON . parse ( content ) : { } ; return data as T ; } , [ validate , content ] ) ; useEffect ( ( ) => { if ( ! isMounted . current || isControlled ) { return ; } const isValid = validate ( ) ; onUpdate ( { data : { raw : content , format : formatContent , } , validate , isValid , } ) ; } , [ onUpdate , content , formatContent , validate , isControlled ] ) ; useEffect ( ( ) => { isMounted . current = true ; return ( ) => { isMounted . current = false ; } ; } , [ ] ) ; return { content , setContent , error , isControlled , } ; } ;