Skip to content

Commit 6c79c94

Browse files
feat(overmind): parallel statecharts
1 parent 0c3722b commit 6c79c94

File tree

8 files changed

+595
-149
lines changed

8 files changed

+595
-149
lines changed

packages/node_modules/overmind-devtools-client/src/components/Chart/index.tsx

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import * as styles from './styles'
99

1010
type Props = {
1111
chart: Chart
12-
statePath: string[]
13-
nestedChart?: NestedChart
12+
statePath: (string | number)[]
13+
nestedChart?: NestedChart | NestedChart[]
1414
}
1515

1616
const ChartComponent: FunctionComponent<Props> = ({
@@ -20,20 +20,38 @@ const ChartComponent: FunctionComponent<Props> = ({
2020
}) => {
2121
const { state, actions } = useOvermind()
2222

23+
if (Array.isArray(nestedChart)) {
24+
return (
25+
<div className={styles.parallelWrapper}>
26+
{nestedChart.map((nestedChartItem, index) => (
27+
<div key={'parallel-' + index} className={styles.parallelSplitter}>
28+
<ChartComponent
29+
chart={chart}
30+
statePath={statePath.concat(index)}
31+
nestedChart={nestedChartItem}
32+
/>
33+
</div>
34+
))}
35+
</div>
36+
)
37+
}
38+
2339
return (
2440
<div className={styles.outerWrapper}>
2541
<div className={styles.wrapper}>
2642
{Object.keys(nestedChart.states).map((key) => {
27-
const isCurrentState = chart.state
28-
.join('.')
29-
.startsWith(statePath.concat(key).join('.'))
43+
const isActiveState = chart.states.reduce((aggr, state) => {
44+
if (aggr) return true
45+
46+
return state.join('.').startsWith(statePath.concat(key).join('.'))
47+
}, false)
3048
return (
3149
<div key={key} className={styles.stateItem}>
3250
<div className={styles.stateNameCell}>
3351
<div
3452
className={styles.stateName}
3553
style={{
36-
backgroundColor: isCurrentState
54+
backgroundColor: isActiveState
3755
? nameToColor(chart.path.join('.'))
3856
: null,
3957
}}
@@ -45,7 +63,7 @@ const ChartComponent: FunctionComponent<Props> = ({
4563
<div
4664
className={styles.selectedLine}
4765
style={{
48-
backgroundColor: isCurrentState
66+
backgroundColor: isActiveState
4967
? nameToColor(chart.path.join('.'))
5068
: null,
5169
}}
@@ -56,7 +74,7 @@ const ChartComponent: FunctionComponent<Props> = ({
5674
<div
5775
className={styles.stateAction}
5876
style={{
59-
borderColor: isCurrentState
77+
borderColor: isActiveState
6078
? nameToColor(chart.path.join('.'))
6179
: null,
6280
}}
@@ -71,7 +89,7 @@ const ChartComponent: FunctionComponent<Props> = ({
7189
<div
7290
className={styles.selectedLine}
7391
style={{
74-
backgroundColor: isCurrentState
92+
backgroundColor: isActiveState
7593
? nameToColor(chart.path.join('.'))
7694
: null,
7795
}}
@@ -82,7 +100,7 @@ const ChartComponent: FunctionComponent<Props> = ({
82100
<div
83101
className={styles.selectedLine}
84102
style={{
85-
backgroundColor: isCurrentState
103+
backgroundColor: isActiveState
86104
? nameToColor(chart.path.join('.'))
87105
: null,
88106
}}
@@ -91,7 +109,7 @@ const ChartComponent: FunctionComponent<Props> = ({
91109
<div
92110
className={styles.onCell}
93111
style={{
94-
borderColor: isCurrentState
112+
borderColor: isActiveState
95113
? nameToColor(chart.path.join('.'))
96114
: null,
97115
}}
@@ -160,7 +178,7 @@ const ChartComponent: FunctionComponent<Props> = ({
160178
<div
161179
className={styles.selectedLine}
162180
style={{
163-
backgroundColor: isCurrentState
181+
backgroundColor: isActiveState
164182
? nameToColor(chart.path.join('.'))
165183
: null,
166184
}}
@@ -174,7 +192,7 @@ const ChartComponent: FunctionComponent<Props> = ({
174192
<div
175193
className={styles.stateAction}
176194
style={{
177-
borderColor: isCurrentState
195+
borderColor: isActiveState
178196
? nameToColor(chart.path.join('.'))
179197
: null,
180198
}}

packages/node_modules/overmind-devtools-client/src/components/Chart/styles.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import { css } from 'emotion'
22

33
import { colors } from '../../theme'
44

5+
export const parallelWrapper = css({
6+
padding: '0.5rem',
7+
})
8+
9+
export const parallelSplitter = css({
10+
borderBottom: `2px dashed ${colors.foreground}`,
11+
})
12+
513
export const outerWrapper = css({
614
overflowY: 'scroll',
715
boxSizing: 'border-box',
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { Child, createElement } from 'overmind-components'
2+
3+
import { Component } from '../../overmind'
4+
import * as styles from './styles'
5+
6+
type Props = {
7+
children: [Child, Child]
8+
minSize: number
9+
defaultSize: number
10+
onChange: (size: number) => void
11+
}
12+
13+
type State = {
14+
isDragging: boolean
15+
size: number
16+
initialSize: number
17+
initialX: number
18+
}
19+
20+
const SplitPane: Component<Props, State> = (
21+
{ onChange, minSize, children },
22+
{ state, changeState }
23+
) => {
24+
return (
25+
<self
26+
onMount={() => {
27+
function onMouseMove(event: MouseEvent) {
28+
if (state.isDragging) {
29+
const newSize = state.initialSize - (state.initialX - event.clientX)
30+
changeState({
31+
size: Math.max(newSize, minSize),
32+
})
33+
}
34+
}
35+
36+
window.addEventListener('mousemove', onMouseMove)
37+
38+
return () => {
39+
window.removeEventListener('mousemove', onMouseMove)
40+
}
41+
}}
42+
className={styles.wrapper}
43+
>
44+
<div
45+
style={{
46+
width: state.size + 'px',
47+
}}
48+
>
49+
{children[0]}
50+
</div>
51+
<div
52+
className={styles.splitter}
53+
onMouseDown={(event) => {
54+
changeState({ isDragging: true, initialX: event.clientX })
55+
}}
56+
onMouseUp={() => {
57+
changeState({
58+
isDragging: false,
59+
})
60+
onChange(state.size)
61+
}}
62+
/>
63+
<div>{children[1]}</div>
64+
</self>
65+
)
66+
}
67+
68+
SplitPane.initialState = ({ defaultSize }) => ({
69+
isDragging: false,
70+
size: defaultSize,
71+
initialSize: defaultSize,
72+
initialX: 0,
73+
})
74+
75+
export default SplitPane
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { css } from 'emotion'
2+
3+
import { colors } from '../../theme'
4+
5+
export const wrapper = css({
6+
padding: '2rem',
7+
display: 'flex',
8+
})
9+
10+
export const splitter = css({
11+
width: 3,
12+
backgroundColor: colors.foreground,
13+
cursor: 'col-resize',
14+
margin: '0 0.5rem',
15+
userSelect: 'none',
16+
})

packages/node_modules/overmind-devtools-client/src/overmind/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export type NestedChart = {
394394
[key: string]: {
395395
entry?: string
396396
exit?: string
397-
chart?: NestedChart
397+
chart?: NestedChart | NestedChart[]
398398
on?: {
399399
[key: string]:
400400
| string
@@ -408,8 +408,8 @@ export type NestedChart = {
408408

409409
export type Chart = {
410410
path: string[]
411-
state: string[]
412-
chart: NestedChart
411+
states: Array<string[]>
412+
chart: NestedChart | NestedChart[]
413413
actions: {
414414
[name: string]: boolean
415415
}

0 commit comments

Comments
 (0)