Skip to content

Commit 4d0e2f9

Browse files
feat(overmind-devtools): change state values
1 parent 4e67d1d commit 4d0e2f9

File tree

10 files changed

+294
-29
lines changed

10 files changed

+294
-29
lines changed

packages/node_modules/overmind-devtools/src/components/ActionPayload/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createElement, FunctionComponent, Fragment, useState } from 'react'
22
import * as styles from './styles'
33
import { useOvermind } from '../../overmind'
4-
import { isValidPayload } from '../../overmind/utils'
4+
import { isValidJson } from '../../overmind/utils'
55
import { colors } from '../../theme'
66

77
const ActionPayload: FunctionComponent = () => {
@@ -13,7 +13,7 @@ const ActionPayload: FunctionComponent = () => {
1313
<input
1414
style={{
1515
borderColor:
16-
!payload || isValidPayload(payload) ? 'transparent' : colors.red,
16+
!payload || isValidJson(payload) ? 'transparent' : colors.red,
1717
}}
1818
disabled={!state.currentApp.selectedActionQuery}
1919
placeholder={

packages/node_modules/overmind-devtools/src/components/Inspector/index.tsx

Lines changed: 167 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,42 @@
1-
import { createElement, FunctionComponent } from 'react'
1+
import { createElement, FunctionComponent, useState, Fragment } from 'react'
22
import { isObject, isArray } from './utils'
3+
import { isValidJson } from '../../overmind/utils'
34
import * as styles from './styles'
45
import { 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

641
type 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

1756
const 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> = ({
72156
type ValueComponentProps = {
73157
value: string | number | boolean
74158
path: string[]
159+
onClickPath?: (path: string[]) => void
160+
selectedStatePath: string
161+
onSubmitState: (newState: string) => void
75162
}
76163

77164
const 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

128265
const 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

packages/node_modules/overmind-devtools/src/components/Inspector/styles.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export const smallWrapper = css({
1717
export const key = css({
1818
marginRight: 5,
1919
color: colors.white,
20+
cursor: 'pointer',
21+
':hover': {
22+
opacity: 0.75,
23+
},
2024
})
2125

2226
export const inlineNested = css({
@@ -48,3 +52,42 @@ export const keyCount = css({
4852
fontsize: 14,
4953
color: colors.white4,
5054
})
55+
56+
export const editValueWrapper = css({
57+
position: 'relative',
58+
})
59+
60+
export const editValuePopup = css({
61+
position: 'absolute',
62+
width: 400,
63+
height: 100,
64+
top: 0,
65+
left: 0,
66+
boxShadow: '0px 10px 13px 0px rgba(0,0,0,0.1)',
67+
})
68+
69+
export const newState = css({
70+
fontFamily: 'inherit',
71+
fontSize: 16,
72+
border: '2px solid transparent',
73+
backgroundColor: colors.white,
74+
color: colors.dark,
75+
outline: 'none',
76+
borderRadius: 3,
77+
width: '100%',
78+
height: '100%',
79+
boxSizing: 'border-box',
80+
})
81+
82+
export const ok = css({
83+
position: 'absolute',
84+
cursor: 'pointer',
85+
top: 0,
86+
right: 0,
87+
border: 0,
88+
outline: 'none',
89+
borderTopRightRadius: 3,
90+
padding: '0.5rem 1rem',
91+
backgroundColor: colors.green,
92+
color: colors.dark,
93+
})

packages/node_modules/overmind-devtools/src/components/State/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ const State: SFC = () => {
2222
const { state, actions } = useOvermind()
2323

2424
return (
25-
<div className={styles.wrapper}>
25+
<div className={styles.wrapper} onClick={() => actions.undoSettingState()}>
2626
<Inspector
2727
value={state.currentApp.state || {}}
28-
expandedPaths={state.expandedStatePaths}
28+
expandedPaths={state.currentApp.expandedStatePaths}
29+
onClickPath={actions.setState}
2930
onToggleExpand={actions.toggleExpandState}
31+
selectedStatePath={state.currentApp.selectedStatePath}
32+
onSubmitState={actions.submitState}
3033
renderPaths={
3134
Object.assign(
3235
{},

0 commit comments

Comments
 (0)