import React , { useState , useEffect } from "react" ; import makeClass from "clsx" ; import { ThemeableElement , useTheme } from "@devtools-ds/themes" ; import { ASTNode , isObject , getPromiseState } from "@devtools-ds/object-parser" ; import styles from "./ObjectInspector.css" ; interface ObjectValueProps extends ThemeableElement < "span" > { /** Type of object. */ ast : ASTNode ; /** Whether or not to show the key */ showKey : boolean ; } param key param value param valueClass param showKey param depth const buildValue = ( key , value , valueClass , showKey , depth ) => { const computedKey = key . includes ( "-" ) ? `"${ key }"` : key ; const isRoot = depth <= 0 ; return ( < span className = { styles . text } > { ! isRoot && showKey && ( < > < span className = { styles . key } > { computedKey } < /span> < span > : & nbsp ; < /span> < />)} < span className = { valueClass } > { value } < /span> < /span>); } ; /** Display a leaf key-value pair with appropriate styles. */ export const ObjectValue = ( props ) => { const { ast , theme , showKey , colorScheme , className , ... html } = props ; const { themeClass } = useTheme ( { theme , colorScheme } , styles ) ; const [ asyncValue , setAsyncValue ] = useState ( < span />); let value = < span />; useEffect ( ( ) => { if ( ast . value instanceof Promise ) { /** Async function to wait for Promise.race */ const waitForPromiseResult = async ( promise ) => { setAsyncValue ( buildValue ( ast . key , `Promise { "${ await getPromiseState ( promise ) }" }` , styles . key , showKey , ast . depth ) ) ; } ; waitForPromiseResult ( ast . value ) ; } } , [ ast , showKey ] ) ; if ( typeof ast . value === "number" || typeof ast . value === "bigint" ) { value = buildValue ( ast . key , String ( ast . value ) , styles . number , showKey , ast . depth ) ; } else if ( typeof ast . value === "boolean" ) { value = buildValue ( ast . key , String ( ast . value ) , styles . boolean , showKey , ast . depth ) ; } else if ( typeof ast . value === "string" ) { value = buildValue ( ast . key , `"${ ast . value }"` , styles . string , showKey , ast . depth ) ; } else if ( typeof ast . value === "undefined" ) { value = buildValue ( ast . key , "undefined" , styles . undefined , showKey , ast . depth ) ; } else if ( typeof ast . value === "symbol" ) { value = buildValue ( ast . key , ast . value . toString ( ) , styles . string , showKey , ast . depth ) ; } else if ( typeof ast . value === "function" ) { value = buildValue ( ast . key , `${ ast . value . name }()` , styles . key , showKey , ast . depth ) ; } else if ( typeof ast . value === "object" ) { if ( ast . value === null ) { value = buildValue ( ast . key , "null" , styles . null , showKey , ast . depth ) ; } else if ( Array . isArray ( ast . value ) ) { value = buildValue ( ast . key , `Array(${ ast . value . length })` , styles . key , showKey , ast . depth ) ; } else if ( ast . value instanceof Date ) { value = buildValue ( ast . key , `Date ${ ast . value . toString ( ) }` , styles . value , showKey , ast . depth ) ; } else if ( ast . value instanceof RegExp ) { value = buildValue ( ast . key , ast . value . toString ( ) , styles . regex , showKey , ast . depth ) ; } else if ( ast . value instanceof Error ) { value = buildValue ( ast . key , ast . value . toString ( ) , styles . error , showKey , ast . depth ) ; } else if ( isObject ( ast . value ) ) { value = buildValue ( ast . key , "{…}" , styles . key , showKey , ast . depth ) ; } else { value = buildValue ( ast . key , ast . value . constructor . name , styles . key , showKey , ast . depth ) ; } } return ( < span className = { makeClass ( themeClass , className ) } { ... html } > { asyncValue } { value } < /span>); } ; ObjectValue . defaultProps = { showKey : true , } ; export default ObjectValue ;