@@ -2,11 +2,150 @@ import React from 'react';
22import PropTypes from 'prop-types' ;
33import { useSelector } from 'react-redux' ;
44import url from 'url' ;
5- import Inspector from 'react-inspector' ;
6- import { withStyles , createMuiTheme , useTheme } from '@material-ui/core/styles' ;
5+ import ExpandIcon from '@material-ui/icons/ExpandMore' ;
6+ import CollapseIcon from '@material-ui/icons/ChevronRight' ;
7+ import TreeView from '@material-ui/lab/TreeView' ;
8+ import TreeItem from '@material-ui/lab/TreeItem' ;
9+ import clsx from 'clsx' ;
10+ import { makeStyles , withStyles , createMuiTheme , useTheme } from '@material-ui/core/styles' ;
711import FormControlLabel from '@material-ui/core/FormControlLabel' ;
812import Switch from '@material-ui/core/Switch' ;
913
14+ /**
15+ * @type {React.Context<keyof object> }
16+ */
17+ const ObjectContext = React . createContext ( '$ROOT' ) ;
18+
19+ /**
20+ * @param {unknown } value
21+ */
22+ function useType ( value ) {
23+ if ( Array . isArray ( value ) ) {
24+ return 'array' ;
25+ }
26+ if ( value === null ) {
27+ return 'null' ;
28+ }
29+
30+ return typeof value ;
31+ }
32+
33+ /**
34+ *
35+ * @param {unknown } value
36+ * @param {ReturnType<typeof useType> } type
37+ */
38+ function useLabel ( value , type ) {
39+ switch ( type ) {
40+ case 'array' :
41+ return `Array(${ value . length } )` ;
42+ case 'null' :
43+ return 'null' ;
44+ case 'undefined' :
45+ return 'undefined' ;
46+ case 'function' :
47+ return `f ${ value . name } ()` ;
48+ case 'object' :
49+ return 'Object' ;
50+ case 'string' :
51+ return `"${ value } "` ;
52+ case 'symbol' :
53+ return `Symbol(${ String ( value ) } )` ;
54+ case 'bigint' :
55+ case 'boolean' :
56+ case 'number' :
57+ default :
58+ return String ( value ) ;
59+ }
60+ }
61+
62+ const useTreeLabelStyles = makeStyles ( {
63+ objectKey : {
64+ color : 'rgb(227, 110, 236)' ,
65+ } ,
66+ objectValue : { } ,
67+ 'type-function' : {
68+ fontStyle : 'italic' ,
69+ } ,
70+ 'type-string' : {
71+ color : 'rgb(233, 63, 59)' ,
72+ } ,
73+ 'type-boolean' : {
74+ color : 'rgb(153, 128, 255);' ,
75+ } ,
76+ 'type-number' : {
77+ color : 'rgb(153, 128, 255);' ,
78+ } ,
79+ } ) ;
80+
81+ function TreeLabel ( { objectKey, objectValue } ) {
82+ const type = useType ( objectValue ) ;
83+ const label = useLabel ( objectValue , type ) ;
84+ const classes = useTreeLabelStyles ( ) ;
85+
86+ return (
87+ < React . Fragment >
88+ < span className = { classes . objectKey } > { objectKey } : </ span >
89+ < span className = { clsx ( classes . objectValue , classes [ `type-${ type } ` ] ) } > { label } </ span >
90+ </ React . Fragment >
91+ ) ;
92+ }
93+ TreeLabel . propTypes = { objectKey : PropTypes . any , objectValue : PropTypes . any } ;
94+
95+ function ObjectTreeItem ( props ) {
96+ const { objectKey, objectValue } = props ;
97+
98+ const keyPrefix = React . useContext ( ObjectContext ) ;
99+
100+ if (
101+ ( objectValue !== null && typeof objectValue === 'object' ) ||
102+ typeof objectValue === 'function'
103+ ) {
104+ const children = Object . keys ( objectValue ) . map ( key => {
105+ return < ObjectTreeItem key = { key } objectKey = { key } objectValue = { objectValue [ key ] } /> ;
106+ } ) ;
107+
108+ if ( objectKey === undefined ) {
109+ return (
110+ < TreeView defaultCollapseIcon = { < ExpandIcon /> } defaultExpandIcon = { < CollapseIcon /> } >
111+ { children }
112+ </ TreeView >
113+ ) ;
114+ }
115+
116+ return (
117+ < TreeItem
118+ nodeId = { `${ keyPrefix } -${ objectKey } ` }
119+ label = { < TreeLabel objectKey = { objectKey } objectValue = { objectValue } /> }
120+ >
121+ < ObjectContext . Provider value = { `${ keyPrefix } -${ objectKey } ` } >
122+ { children }
123+ </ ObjectContext . Provider >
124+ </ TreeItem >
125+ ) ;
126+ }
127+
128+ return (
129+ < TreeItem
130+ nodeId = { `${ keyPrefix } -${ objectKey } ` }
131+ label = { < TreeLabel objectKey = { objectKey } objectValue = { objectValue } /> }
132+ />
133+ ) ;
134+ }
135+ ObjectTreeItem . propTypes = { objectKey : PropTypes . any , objectValue : PropTypes . any } ;
136+
137+ function Inspector ( props ) {
138+ const { data } = props ;
139+
140+ return < ObjectTreeItem objectValue = { data } /> ;
141+ }
142+
143+ Inspector . propTypes = {
144+ data : PropTypes . any ,
145+ /* expandLevel: PropTypes.number,
146+ expandPaths: PropTypes.arrayOf(PropTypes.string), */
147+ } ;
148+
10149const styles = theme => ( {
11150 root : {
12151 padding : theme . spacing ( 2 ) ,
0 commit comments