/** * See `@tdb/ui.test` for UI stories. * See: * https://github.com/xyc/react-inspector */ import { React, css, GlamorValue, value } from '../common'; import { Editor } from './Editor'; import { DEFAULTS } from './constants'; import { ReactInspector, ObjectLabel, ObjectRootLabel, ObjectName, THEME, } from './libs'; export interface IObjectViewProps { data: any; name?: string; expandLevel?: number; showNonenumerable?: boolean; expandPaths?: string | string[]; fontSize?: number; theme?: 'LIGHT' | 'DARK'; style?: GlamorValue; } export interface IObjectViewState { data?: any; isLoading?: boolean; } interface INodeRendererOptions { depth: number; name: string; data: any; isNonenumerable: boolean; expanded: boolean; } /** * Views an Object as a visual tree. */ export class ObjectView extends React.PureComponent< IObjectViewProps, IObjectViewState > { public state: IObjectViewState = {}; private isUnmounted = false; public componentWillMount() { this.loadData(); } public componentDidUpdate( prevProps: IObjectViewProps, prevState: IObjectViewState, ) { if (this.props.data !== prevProps.data && !this.isUnmounted) { this.loadData(); } } public componentWillUnmount() { this.isUnmounted = true; } public render() { let { data } = this.state; const { name, expandLevel = 1, showNonenumerable = false, expandPaths, style, } = this.props; if (this.state.isLoading) { data = 'Loading...'; } return (
); } private get theme() { const { fontSize = DEFAULTS.FONT_SIZE } = this.props; const fontSizeCss = `${fontSize}px`; const lineHeightCss = '1.5em'; return { ...this.baseTheme, BASE_BACKGROUND_COLOR: 'transparent', BASE_FONT_SIZE: fontSizeCss, TREENODE_FONT_SIZE: fontSizeCss, BASE_LINE_HEIGHT: lineHeightCss, TREENODE_LINE_HEIGHT: lineHeightCss, }; } private get baseTheme() { const { theme = 'LIGHT' } = this.props; switch (theme) { case 'LIGHT': return THEME.CHROME_LIGHT; case 'DARK': return THEME.CHROME_DARK; default: throw new Error(`Theme '${theme}' not supported.`); } } private async loadData() { let { data } = this.props; if (value.isPromise(data)) { this.setState({ isLoading: true }); data = await data; } this.setState({ data, isLoading: false }); } public renderNode = (props: INodeRendererOptions) => { const { depth, name, data, isNonenumerable } = props; if (depth === 0) { // NB: Don't show preview of object on root. return this.renderRootNode(props); } else { // TODO // return this.renderEditorNode(props); return ( ); } }; public renderRootNode = (props: INodeRendererOptions) => { const { data, name } = props; const rootData = Array.isArray(data) ? data : {}; return ; }; public renderEditorNode = (props: INodeRendererOptions) => { const { name, isNonenumerable } = props; return ( : ); }; }