1
1
import randomWords from "random-words" ;
2
+ import { v4 as uuid } from "uuid" ;
2
3
import React , { useEffect , useMemo } from "react" ;
3
4
import { connectToDB , getConnection } from "./sharedb" ;
4
5
import {
@@ -8,8 +9,12 @@ import {
8
9
useLocation ,
9
10
} from "react-router-dom" ;
10
11
12
+ interface Node {
13
+ text : string ;
14
+ }
15
+
11
16
type Flow = {
12
- nodes : Record < string , { } > ;
17
+ nodes : Record < string , Node > ;
13
18
edges : Array < [ string | null , string ] > ;
14
19
} ;
15
20
@@ -46,7 +51,7 @@ function useFlow(config: {
46
51
// Methods
47
52
48
53
const addNode = React . useCallback ( ( ) => {
49
- doc . submitOp ( [ { p : [ "nodes" , randomWords ( ) ] , oi : { } } ] ) ;
54
+ doc . submitOp ( [ { p : [ "nodes" , uuid ( ) ] , oi : { text : randomWords ( ) } } ] ) ;
50
55
} , [ doc ] ) ;
51
56
52
57
const removeNode = React . useCallback (
@@ -81,16 +86,13 @@ const Flow: React.FC<{ id: string }> = ({ id }) => {
81
86
}
82
87
83
88
return (
84
- < div >
85
- { Object . keys ( flow . state . nodes ) . map ( ( k ) => (
86
- < Node key = { k } onRemove = { flow . removeNode } id = { k } />
87
- ) ) }
89
+ < main >
88
90
< button
89
91
onClick = { ( ) => {
90
92
flow . addNode ( ) ;
91
93
} }
92
94
>
93
- ADD
95
+ Add
94
96
</ button >
95
97
< button
96
98
onClick = { ( ) => {
@@ -101,25 +103,67 @@ const Flow: React.FC<{ id: string }> = ({ id }) => {
101
103
} ) ;
102
104
} }
103
105
>
104
- RESET
106
+ Import flow
105
107
</ button >
106
- </ div >
108
+ < button
109
+ onClick = { ( ) => {
110
+ flow . reset ( {
111
+ nodes : { } ,
112
+ edges : [ ] ,
113
+ } ) ;
114
+ } }
115
+ >
116
+ Reset
117
+ </ button >
118
+ { Object . keys ( flow . state . nodes ) . map ( ( k ) => (
119
+ < NodeView
120
+ key = { k }
121
+ onRemove = { flow . removeNode }
122
+ id = { k }
123
+ node = { flow . state . nodes [ k ] }
124
+ />
125
+ ) ) }
126
+ </ main >
107
127
) ;
108
128
} ;
109
129
110
- const Node = React . memo (
111
- ( { id, onRemove } : { id : string ; onRemove : ( id : string ) => void } ) => (
112
- < h1
113
- onClick = { ( ) => {
114
- // remove the node
115
- onRemove ( id ) ;
116
- } }
117
- >
118
- { id } { Math . round ( Math . random ( ) * 1000 ) }
119
- </ h1 >
120
- )
130
+ const NodeView = React . memo (
131
+ ( {
132
+ id,
133
+ node,
134
+ onRemove,
135
+ } : {
136
+ id : string ;
137
+ node : Node ;
138
+ onRemove : ( id : string ) => void ;
139
+ } ) => (
140
+ < div className = "node" >
141
+ < button
142
+ className = "remove-button"
143
+ onClick = { ( ) => {
144
+ onRemove ( id ) ;
145
+ } }
146
+ >
147
+ ×
148
+ </ button >
149
+ < p >
150
+ { node . text || "unset" } { Math . round ( Math . random ( ) * 1000 ) }
151
+ </ p >
152
+ </ div >
153
+ ) ,
154
+ ( prevProps , nextProps ) =>
155
+ prevProps . id === nextProps . id &&
156
+ prevProps . onRemove === nextProps . onRemove &&
157
+ JSON . stringify ( prevProps . node ) === JSON . stringify ( nextProps . node )
121
158
) ;
122
159
160
+ const SimpleLink = ( { to } : { to : string } ) => {
161
+ const location = useLocation ( ) ;
162
+ return (
163
+ < Link to = { to } > { location . hash === to ? < strong > { to } </ strong > : to } </ Link >
164
+ ) ;
165
+ } ;
166
+
123
167
const App = ( ) => {
124
168
const history = useHistory ( ) ;
125
169
const location = useLocation ( ) ;
@@ -145,7 +189,8 @@ const App = () => {
145
189
return (
146
190
< div >
147
191
< nav >
148
- < Link to = "#direct" > #direct</ Link > < Link to = "#captain" > #captain</ Link > { " " }
192
+ < SimpleLink to = "#direct" />
193
+ < SimpleLink to = "#captain" />
149
194
< button
150
195
onClick = { ( ) => {
151
196
history . push ( `#${ randomWords ( ) } ` ) ;
0 commit comments