1- import { createElement , FunctionComponent } from 'react'
1+ import { createElement , FunctionComponent , useState , Fragment } from 'react'
22import { isObject , isArray } from './utils'
3+ import { isValidJson } from '../../overmind/utils'
34import * as styles from './styles'
45import { css } from 'emotion'
6+ import { colors } from '../../theme'
7+
8+ type EditValueProps = {
9+ value : any
10+ onSubmit : ( newState : string ) => void
11+ }
12+
13+ const EditValue : FunctionComponent < EditValueProps > = ( { value, onSubmit } ) => {
14+ const [ state , setState ] = useState ( ( ) => JSON . stringify ( value , null , 2 ) )
15+ const isValid = isValidJson ( state )
16+
17+ return (
18+ < span
19+ className = { styles . editValueWrapper }
20+ onClick = { ( event ) => event . stopPropagation ( ) }
21+ >
22+ < div className = { styles . editValuePopup } >
23+ < textarea
24+ value = { state }
25+ onChange = { ( event ) => setState ( event . currentTarget . value ) }
26+ className = { styles . newState }
27+ style = { {
28+ borderColor : isValid ? null : colors . red ,
29+ } }
30+ />
31+ { isValid ? (
32+ < button onClick = { ( ) => onSubmit ( state ) } className = { styles . ok } >
33+ OK
34+ </ button >
35+ ) : null }
36+ </ div >
37+ </ span >
38+ )
39+ }
540
641type NestedProps = {
742 startBracket : string
@@ -10,22 +45,55 @@ type NestedProps = {
1045 path : string [ ]
1146 keys : string [ ]
1247 isArray : boolean
48+ value : any
1349 children : ( ) => React . ReactNode
1450 onToggleExpand : ( path : string [ ] ) => void
51+ onClickPath ?: ( path : string [ ] ) => void
52+ selectedStatePath : string
53+ onSubmitState : ( newState : string ) => void
1554}
1655
1756const Nested : FunctionComponent < NestedProps > = ( {
1857 keys,
1958 expandedPaths,
2059 path,
2160 onToggleExpand,
61+ onClickPath,
2262 startBracket,
2363 endBracket,
2464 children,
2565 isArray,
66+ selectedStatePath,
67+ value,
68+ onSubmitState,
2669} ) => {
2770 const shouldCollapse = ! expandedPaths . includes ( path . join ( '.' ) )
2871
72+ if ( selectedStatePath && path . join ( '.' ) === selectedStatePath ) {
73+ return (
74+ < div
75+ className = { styles . inlineNested }
76+ onClick = { ( event ) => {
77+ event . stopPropagation ( )
78+ onToggleExpand ( path )
79+ } }
80+ >
81+ { path . length ? (
82+ < span
83+ className = { styles . key }
84+ onClick = { ( event ) => {
85+ event . stopPropagation ( )
86+ onClickPath ( path )
87+ } }
88+ >
89+ { path [ path . length - 1 ] } :
90+ </ span >
91+ ) : null }
92+ < EditValue value = { value } onSubmit = { onSubmitState } />
93+ </ div >
94+ )
95+ }
96+
2997 if ( shouldCollapse ) {
3098 return (
3199 < div
@@ -36,7 +104,15 @@ const Nested: FunctionComponent<NestedProps> = ({
36104 } }
37105 >
38106 { path . length ? (
39- < span className = { styles . key } > { path [ path . length - 1 ] } :</ span >
107+ < span
108+ className = { styles . key }
109+ onClick = { ( event ) => {
110+ event . stopPropagation ( )
111+ onClickPath ( path )
112+ } }
113+ >
114+ { path [ path . length - 1 ] } :
115+ </ span >
40116 ) : null }
41117 { startBracket }
42118 < span className = { styles . keyCount } >
@@ -59,7 +135,15 @@ const Nested: FunctionComponent<NestedProps> = ({
59135 } }
60136 >
61137 { path . length ? (
62- < span className = { styles . key } > { path [ path . length - 1 ] } :</ span >
138+ < span
139+ className = { styles . key }
140+ onClick = { ( event ) => {
141+ event . stopPropagation ( )
142+ onClickPath ( path )
143+ } }
144+ >
145+ { path [ path . length - 1 ] } :
146+ </ span >
63147 ) : null }
64148 { startBracket }
65149 </ div >
@@ -72,12 +156,37 @@ const Nested: FunctionComponent<NestedProps> = ({
72156type ValueComponentProps = {
73157 value : string | number | boolean
74158 path : string [ ]
159+ onClickPath ?: ( path : string [ ] ) => void
160+ selectedStatePath : string
161+ onSubmitState : ( newState : string ) => void
75162}
76163
77164const ValueComponent : FunctionComponent < ValueComponentProps > = ( {
78165 value,
79166 path,
167+ onClickPath,
168+ selectedStatePath,
169+ onSubmitState,
80170} ) => {
171+ if ( selectedStatePath && path . join ( '.' ) === selectedStatePath ) {
172+ return (
173+ < div className = { styles . genericValue } >
174+ { path . length ? (
175+ < span
176+ className = { styles . key }
177+ onClick = { ( event ) => {
178+ event . stopPropagation ( )
179+ onClickPath ( path )
180+ } }
181+ >
182+ { path [ path . length - 1 ] } :
183+ </ span >
184+ ) : null }
185+ < EditValue value = { value } onSubmit = { onSubmitState } />
186+ </ div >
187+ )
188+ }
189+
81190 if (
82191 typeof value === 'string' &&
83192 value [ 0 ] === '[' &&
@@ -86,8 +195,16 @@ const ValueComponent: FunctionComponent<ValueComponentProps> = ({
86195 return (
87196 < div className = { styles . otherValue } >
88197 { path . length ? (
89- < span className = { styles . key } > { path [ path . length - 1 ] } :</ span >
90- ) : null } { ' ' }
198+ < span
199+ className = { styles . key }
200+ onClick = { ( event ) => {
201+ event . stopPropagation ( )
202+ onClickPath ( path )
203+ } }
204+ >
205+ { path [ path . length - 1 ] } :
206+ </ span >
207+ ) : null }
91208 { value . substr ( 1 , value . length - 2 ) }
92209 </ div >
93210 )
@@ -97,17 +214,34 @@ const ValueComponent: FunctionComponent<ValueComponentProps> = ({
97214 return (
98215 < div className = { styles . stringValue } >
99216 { path . length ? (
100- < span className = { styles . key } > { path [ path . length - 1 ] } :</ span >
101- ) : null } { ' ' }
217+ < span
218+ className = { styles . key }
219+ onClick = { ( event ) => {
220+ event . stopPropagation ( )
221+ onClickPath ( path )
222+ } }
223+ >
224+ { path [ path . length - 1 ] } :
225+ </ span >
226+ ) : null }
102227 "{ value } "
103228 </ div >
104229 )
105230 }
231+
106232 return (
107233 < div className = { styles . genericValue } >
108234 { path . length ? (
109- < span className = { styles . key } > { path [ path . length - 1 ] } :</ span >
110- ) : null } { ' ' }
235+ < span
236+ className = { styles . key }
237+ onClick = { ( event ) => {
238+ event . stopPropagation ( )
239+ onClickPath ( path )
240+ } }
241+ >
242+ { path [ path . length - 1 ] } :
243+ </ span >
244+ ) : null }
111245 { String ( value ) }
112246 </ div >
113247 )
@@ -122,15 +256,21 @@ type InspectorProps = {
122256 expandedPaths : string [ ]
123257 small ?: boolean
124258 onToggleExpand : ( path : string [ ] ) => void
259+ onClickPath ?: ( path : string [ ] ) => void
125260 renderPaths ?: RenderPaths
261+ selectedStatePath ?: string
262+ onSubmitState ?: ( newState : string ) => void
126263}
127264
128265const Inspector : FunctionComponent < InspectorProps > = ( {
129266 value,
130267 expandedPaths,
131268 small,
132269 onToggleExpand,
270+ onClickPath = ( ) => { } ,
133271 renderPaths,
272+ selectedStatePath = '' ,
273+ onSubmitState = ( ) => { } ,
134274} ) => {
135275 function renderValue ( path : string [ ] , value : any , renderPaths ?: RenderPaths ) {
136276 const wrapper = renderPaths && renderPaths [ path . join ( '.' ) ]
@@ -144,9 +284,13 @@ const Inspector: FunctionComponent<InspectorProps> = ({
144284 endBracket = "}"
145285 path = { path }
146286 expandedPaths = { expandedPaths }
287+ onClickPath = { onClickPath }
147288 onToggleExpand = { onToggleExpand }
148289 keys = { Object . keys ( value ) }
149290 isArray = { false }
291+ value = { value }
292+ selectedStatePath = { selectedStatePath }
293+ onSubmitState = { onSubmitState }
150294 >
151295 { ( ) =>
152296 Object . keys ( value ) . map ( ( key ) =>
@@ -163,9 +307,13 @@ const Inspector: FunctionComponent<InspectorProps> = ({
163307 endBracket = "]"
164308 path = { path }
165309 expandedPaths = { expandedPaths }
310+ onClickPath = { onClickPath }
166311 onToggleExpand = { onToggleExpand }
167312 keys = { Object . keys ( value ) }
168313 isArray
314+ value = { value }
315+ selectedStatePath = { selectedStatePath }
316+ onSubmitState = { onSubmitState }
169317 >
170318 { ( ) =>
171319 value . map ( ( _ , index ) =>
@@ -175,7 +323,16 @@ const Inspector: FunctionComponent<InspectorProps> = ({
175323 </ Nested >
176324 )
177325 } else {
178- node = < ValueComponent key = { path . join ( '.' ) } path = { path } value = { value } />
326+ node = (
327+ < ValueComponent
328+ key = { path . join ( '.' ) }
329+ path = { path }
330+ value = { value }
331+ onClickPath = { onClickPath }
332+ selectedStatePath = { selectedStatePath }
333+ onSubmitState = { onSubmitState }
334+ />
335+ )
179336 }
180337
181338 return wrapper ? wrapper ( node ) : node
0 commit comments