1
1
2
2
/* IMPORT */
3
3
4
- import { Observable , ObservableMaybe } from 'voby' ;
5
- import { $ , createElement , render , template , For , Fragment } from 'voby' ;
4
+ import { FunctionMaybe , Observable , ObservableMaybe } from 'voby' ;
5
+ import { $ , createElement , render , template , useSelector , For , Fragment } from 'voby' ;
6
6
7
7
window . React = { createElement, Fragment} ;
8
8
9
9
/* TYPES */
10
10
11
- type IDatum = { id : string , label : Observable < string > , selected : Observable < boolean > , className : Observable < string > } ;
11
+ type IDatum = { id : number , label : Observable < string > } ;
12
12
13
13
type IData = IDatum [ ] ;
14
14
@@ -18,28 +18,20 @@ const rand = ( max: number ): number => {
18
18
return Math . round ( Math . random ( ) * 1000 ) % max ;
19
19
} ;
20
20
21
- const uuid = ( ( ) => {
22
- let counter = 1 ;
23
- return ( ) : string => {
24
- return String ( counter ++ ) ;
25
- } ;
26
- } ) ( ) ;
27
-
28
21
const buildData = ( ( ) => {
29
22
const adjectives = [ 'pretty' , 'large' , 'big' , 'small' , 'tall' , 'short' , 'long' , 'handsome' , 'plain' , 'quaint' , 'clean' , 'elegant' , 'easy' , 'angry' , 'crazy' , 'helpful' , 'mushy' , 'odd' , 'unsightly' , 'adorable' , 'important' , 'inexpensive' , 'cheap' , 'expensive' , 'fancy' ] ;
30
23
const colors = [ 'red' , 'yellow' , 'blue' , 'green' , 'pink' , 'brown' , 'purple' , 'brown' , 'white' , 'black' , 'orange' ] ;
31
24
const nouns = [ 'table' , 'chair' , 'house' , 'bbq' , 'desk' , 'car' , 'pony' , 'cookie' , 'sandwich' , 'burger' , 'pizza' , 'mouse' , 'keyboard' ] ;
25
+ let uuid = 1 ;
32
26
return ( length : number ) : IData => {
33
27
const data : IData = new Array ( length ) ;
34
28
for ( let i = 0 ; i < length ; i ++ ) {
35
- const id = uuid ( ) ;
29
+ const id = uuid ++ ;
36
30
const adjective = adjectives [ rand ( adjectives . length ) ] ;
37
31
const color = colors [ rand ( colors . length ) ] ;
38
32
const noun = nouns [ rand ( nouns . length ) ] ;
39
33
const label = $ ( `${ adjective } ${ color } ${ noun } ` ) ;
40
- const selected = $ ( false ) ;
41
- const className = $ ( '' ) ;
42
- const datum : IDatum = { id, label, selected, className } ;
34
+ const datum = { id, label } ;
43
35
data [ i ] = datum ;
44
36
} ;
45
37
return data ;
@@ -52,8 +44,8 @@ const Model = (() => {
52
44
53
45
/* STATE */
54
46
55
- let $data = $ < IDatum [ ] > ( [ ] ) ;
56
- let selected : IDatum | null = null ;
47
+ const $data = $ < IDatum [ ] > ( [ ] ) ;
48
+ const $ selected = $ ( - 1 ) ;
57
49
58
50
/* API */
59
51
@@ -71,14 +63,16 @@ const Model = (() => {
71
63
} ;
72
64
73
65
const add = ( ) : void => {
74
- $data ( $data ( ) . concat ( buildData ( 1000 ) ) ) ;
66
+ const data = $data ( ) ;
67
+ data . push . apply ( data , buildData ( 1000 ) ) ;
68
+ $data . emit ( ) ;
75
69
} ;
76
70
77
71
const update = ( ) : void => {
78
72
const data = $data ( ) ;
79
73
for ( let i = 0 , l = data . length ; i < l ; i += 10 ) {
80
74
const { label} = data [ i ] ;
81
- label ( label ( ) + ' !!!' ) ;
75
+ label . update ( label => label + ' !!!' ) ;
82
76
}
83
77
} ;
84
78
@@ -87,50 +81,40 @@ const Model = (() => {
87
81
if ( data . length <= 998 ) return ;
88
82
const datum1 = data [ 1 ] ;
89
83
const datum998 = data [ 998 ] ;
90
- const data2 = data . slice ( ) ;
91
- data2 [ 1 ] = datum998 ;
92
- data2 [ 998 ] = datum1 ;
93
- $data ( data2 ) ;
84
+ data [ 1 ] = datum998 ;
85
+ data [ 998 ] = datum1 ;
86
+ $data . emit ( ) ;
94
87
} ;
95
88
96
89
const clear = ( ) : void => {
97
90
$data ( [ ] ) ;
98
91
} ;
99
92
100
- const remove = ( id : string ) : void => {
93
+ const remove = ( id : number ) : void => {
101
94
const data = $data ( ) ;
102
95
const index = data . findIndex ( datum => datum . id === id ) ;
103
96
if ( index === - 1 ) return ;
104
- $data ( data . slice ( 0 , index ) . concat ( data . slice ( index + 1 ) ) ) ;
97
+ data . splice ( index , 1 ) ;
98
+ $data . emit ( ) ;
105
99
} ;
106
100
107
- const select = ( id : string ) : void => {
108
- if ( selected ) {
109
- selected . selected ( false ) ;
110
- selected . className ( '' ) ;
111
- selected = null ;
112
- }
113
- const data = $data ( ) ;
114
- const datum = data . find ( datum => datum . id === id ) ;
115
- if ( ! datum ) return ;
116
- datum . selected ( true ) ;
117
- datum . className ( 'danger' ) ;
118
- selected = datum ;
101
+ const select = ( id : number ) : void => {
102
+ $selected ( id ) ;
119
103
} ;
120
104
121
- return { $data, selected, run, runLots, runWith, add, update, swapRows, clear, remove, select } ;
105
+ return { $data, $ selected, run, runLots, runWith, add, update, swapRows, clear, remove, select } ;
122
106
123
107
} ) ( ) ;
124
108
125
109
/* MAIN */
126
110
127
- const Button = ( { id, text, onClick } : { id : string , text : string , onClick : ( ( event : MouseEvent ) => any ) } ) : JSX . Element => (
111
+ const Button = ( { id, text, onClick } : { id : string | number , text : string , onClick : ObservableMaybe < ( ( event : MouseEvent ) => any ) > } ) : JSX . Element => (
128
112
< div class = "col-sm-6 smallpad" >
129
113
< button id = { id } class = "btn btn-primary btn-block" type = "button" onClick = { onClick } > { text } </ button >
130
114
</ div >
131
115
) ;
132
116
133
- const RowDynamic = ( { id, label, className, onSelect, onRemove } : { id : ObservableMaybe < string > , label : ObservableMaybe < string > , className : ObservableMaybe < string > , onSelect : ObservableMaybe < ( ( event : MouseEvent ) => any ) > , onRemove : ObservableMaybe < ( ( event : MouseEvent ) => any ) > } ) : JSX . Element => (
117
+ const RowDynamic = ( { id, label, className, onSelect, onRemove } : { id : FunctionMaybe < string | number > , label : FunctionMaybe < string > , className : FunctionMaybe < string > , onSelect : ObservableMaybe < ( ( event : MouseEvent ) => any ) > , onRemove : ObservableMaybe < ( ( event : MouseEvent ) => any ) > } ) : JSX . Element => (
134
118
< tr className = { className } >
135
119
< td class = "col-md-1" > { id } </ td >
136
120
< td class = "col-md-4" >
@@ -149,7 +133,8 @@ const RowTemplate = template ( RowDynamic, { recycle: true } );
149
133
150
134
const App = ( ) : JSX . Element => {
151
135
152
- const { $data, run, runLots, add, update, clear, swapRows, select, remove} = Model ;
136
+ const { $data, $selected, run, runLots, add, update, clear, swapRows, select, remove} = Model ;
137
+ const isSelected = useSelector ( $selected ) ;
153
138
154
139
return (
155
140
< div class = "container" >
@@ -174,7 +159,8 @@ const App = (): JSX.Element => {
174
159
< tbody >
175
160
< For values = { $data } >
176
161
{ ( datum : IDatum ) => {
177
- const { id, label, className} = datum ;
162
+ const { id, label} = datum ;
163
+ const className = ( ) => isSelected ( id ) ? 'danger' : '' ;
178
164
const onSelect = select . bind ( undefined , id ) ;
179
165
const onRemove = remove . bind ( undefined , id ) ;
180
166
const props = { id, label, className, onSelect, onRemove} ;
0 commit comments